Skip to main content

Full text of "The Atari BASIC source book"

See other formats


A COMPUTE! Books Publication 



$12.95 



The Atari BASIC 




A complete explanation of the inside workings of Atari 

BASIC, along with the original source code. For 

intermediate and advanced programmers. 



Bill Wilkinson 

Kathleen O'Brien 

Paul Laughton 



3 

3 

3 
3 
3 
3 

3 

3 

3 
3 
3 



3 
3 
3 

3 



-* 
1 






From COMPUTE! Books and 
Optimized Systems Software, Inc. 



The Atari BASIC 

SOURCE 
BOOK 



Compiled by Bill Wilkinson 
Optimized Systems Software, Inc. 

With the assistance of 
Kathleen O'Brien and Paul Laughton 



COMPUTErPublicationsJnc© 

A. Subsidiary 01 American Broadcasting Companies. Inc ^^^^ 

ATARI is a registered trademark of Atari, Inc. 



COMPUTE! Books is a division of COMPUTE! Publications, Inc., a subsidiary of 
American Broadcasting Companies, Inc. 

Editorial mailing address is: 
PO Box 5406 

Greensboro, NC 27403 USA 
(919) 275-9809 

Optimized Systems Services, Inc., is located at: 
10379 Lansdale Avenue 
Cupertino, CA 95014 USA 
(408) 446-3099 

All reasonable care has been taken in the writing, testing, and correcting of the text and 
of the software within this book. There is, however, no expressed or implied warranty 
of any kind from the authors or publishers with respect to the text or software herein 
contained. In the event of any damages resulting from the use of the text or the soft- 
ware in this book, or from undocumented or documented manufacturer's changes in 
Atari BASIC made before or after the publication of this book, the authors or publishers 
shall be in no sense liable. 

Copyright © 1983 text, COMPUTE! Publications, Inc. 

Copyright © 1978, 1979, 1983 program listings, Optimized Systems Software, Inc. All 

rights reserved. 

Reproduction or translation of any part of this work beyond that permitted by sections 
107 and 108 of the United States Copyright Act without the permission of the copyright 
owner is unlawful. 

Printed in the United States of America 

ISBN 0-942386-15-9 

10 987654321 



II 



Table of Contents 



Publisher's Foreword v 

Acknowledgments vii 

Preface ix 

Part One: Inside Atari BASIC 

1 Atari BASIC: A High-level Language Translator 1 

2 Internal Design Overview 7 

3 Memory Usage 13 

4 Program Editor 25 

5 The Pre-compiler 33 

6 Execution Overview 49 

7 Execute Expression 55 

8 Execution Boundary Conditions 71 

9 Program Flow Control Statements 75 

10 Tokenized Program Save and Load 81 

11 The LIST and ENTER Statements 85 

12 Atari Hardware Control Statements 91 

13 External Data I/O Statements 95 

14 Internal I/O Statements 103 

15 Miscellaneous Statements 105 

16 Initialization 109 

Part Two: Directly Accessing Atari BASIC 

Introduction to Part Two 113 

1 Hexadecimal Numbers 115 

2 PEEKing and POKEing 119 

3 Listing Variables in Use 123 

4 Variable Values 125 

5 Examining the Statement Table 129 

6 Viewing the Runtime Stack 133 

7 Fixed Tokens 135 

8 What Takes Precedence? 137 

9 Using What We Know 139 

Part Three: Atari BASIC Source Code 

Source Code Listing 143 

iii 



Appendices 

A Macros in Source Code 273 

B The Bugs in Atari BASIC 275 

C Labels and Hexadecimal Addresses 281 

Index 285 



IV 



Publisher's 
Foreword 



It's easy to take a computer language like Atari BASIC for 
granted. But every PEEK and POKE, every FOR-NEXT loop 
and IF-THEN- branch, is really a miniprogram in itself. Taken 
together, they become a powerful tool kit. And, as Atari 
owners know, there are few home-computer languages as 
powerful and versatile — from editing to execution — as Atari 
BASIC. 

With this book, the Atari BASIC tool kit is unlocked. The 
creators of Atari BASIC and COMPUTE! Publications now offer 
you, for the first time, a detailed, inside look at exactly how a 
major computer manufacturer's primary language works. 

For intermediate programmers, the thorough and careful 
explanations in Parts 1 and 2 will help you understand exactly 
what is happening in your Atari computer as you edit and run 
your programs. 

For advanced programmers, Part 3 provides a complete 
listing of the source code for Atari BASIC, so that your machine 
language programs can make use of the powerful routines built 
into that 8K cartridge. 

And for programmers at all levels, by the time you're 
through studying this book you'll feel that you've seen a whole 
computer language at work. 

Special thanks are due to Bill Wilkinson, the creative force 
behind Atari BASIC and many other excellent programs for 
Atari and other computers, for his willingness to share 
copyrighted materials with computer users. Readers of 
COMPUTE! Magazine already know him as a regular 
columnist, and in this book he continues his tradition of clear 
explanations and understandable writing. 



Acknowledgments 



As far as we know, this is the first time that the actual source 
listing of a major manufacturer's primary computer language 
has been made available to the general public. 

As with our previous COMPUTE! Publications book Inside 
Atari DOS, this book contains much more than simply a source 
listing. All major routines are examined and explained. We 
hope that when you finish reading this book you will have a 
better understanding of and appreciation for the design and 
work which go into as sophisticated a program as Atari BASIC. 

This book is the result of the efforts of many people. The 
initial credit must go to Richard Mansfield of COMPUTE! 
Publications for serving as our goad and go-between. Without 
his (and COMPUTE!' s) insistence, this book might never have 
been written. Without his patience and guidance, the contents 
of this book might not have been nearly as interesting. 

To Kathleen O'Brien and Paul Laughton must go the lion's 
share of the authoring credits. Between them, they have done 
what I believe is a very creditable job of explaining a very 
difficult subject, the internal workings of Atari BASIC. In fact, 
Part I of this book is entirely their work. Of course, their ability 
to explain the listing may not be so surprising. After all, 
between them they wrote almost all of the original code for 
Atari BASIC. So, even though Paul and Kathleen are not 
associated with Optimized Systems Software, we were pleased 
to have their invaluable help in writing this book and hope that 
they receive some of the credit which has long been due them. 

Mike Peters was responsible for taking our old, almost 
unreadable copies of the source code diskettes for Atari BASIC 
and converting them to another machine, using another 
assembler, and formatting the whole thing into an acceptable 
form for this book. This isn't surprising either, since Mike 
keypunched the original (yes, on cards). 

And I am Bill Wilkinson, the one responsible for the rest of 
this book. In particular, I hope you will find that a good 
amount of the material in Part II will aid you in understanding 
how to make the best use of this book. 



Vll 



The listing of Atari BASIC is reproduced here courtesy of 
OSS, Inc., which now owns its copyright and most other 
associated rights. 



Vlll 



Preface 



In 1978, Atari, Inc., purchased a copy of Microsoft BASIC for 
the 6502 microprocessor (similar to the version from which 
Applesoft is derived). After laboring for quite some time, the 
people of Atari still couldn't make it do everything they wanted 
it to in the ROM space they had available. And there was a 
deadline fast approaching: the January 1979 Las Vegas 
Consumer Electronics Show (CES). 

At that time, Kathleen, Paul, Mike and I all worked for 
Shepardson Microsystems, Inc. (SMI). Though little known 
by the public, SMI was reasonably successful in producing 
some very popular microcomputer software, including the 
original Apple DOS, Cromemco's 16K and 32K BASICs, and 
more. So it wasn't too surprising that Atari had heard of us. 

And they asked us: Did we want to try to fix Microsoft 
BASIC for them? Well, not really. Did we think we could write 
an all-new BASIC in a reasonable length of time? Yes. And 
would we bet a thousand dollars a week on our ability to do so? 

While Bob Shepardson negotiated with Atari and I wrote 
the preliminary specifications for the language (yes, I'm the 
culprit), time was passing all too rapidly. Finally, on 6 October 
1978, Atari's Engineering Department gave us the okay to 
proceed. 

The schedule? Produce both a BASIC and a Disk File 
Manager (which became Atari DOS) in only six months. And, 
to make sure the pressure was intense, they gave us a $1000-a- 
week incentive (if we were early) or penalty (if we were late). 

But Paul Laughton and Kathleen O'Brien plunged into it. 
And, although the two of them did by far the bulk of the work, 
there was a little help from Paul Krasno (who implemented the 
transcendental routines), Mike Peters (who did a lot of 
keypunching and operating), and me (who designed the 
floating point scheme and stood around in the way a lot). Even 
Bob Shepardson got into the act, modifying his venerable 
IMP-16 assembler to accept the special syntax table mnemonics 
that Paul invented (and which we paraphrase in the current 
listing via macros). 



IX 



Atari delivered the final signed copy of the purchase order 
on 28 December 1978, two and a half months into the project. 
But it didn't really matter: Paul and Kathy were on vacation, 
having delivered the working product more than a week 
before ! 

So Atari took Atari BASIC to CES, and Shepardson 
Microsystems faded out of the picture. As for the bonus for 
early delivery — there was a limit on how much the incentive 
could be. Darn. 

The only really unfortunate part of all this was that Atari 
got the BASIC so early that they moved up their ROM 
production schedule and committed to a final product before 
we had a chance to do a second round of bug fixing. 

And now? Mike and I are running Optimized Systems 
Software, Inc. And even though Paul and Kathleen went their 
own way, we have kept in touch enough to make this book 
possible. 



Part One 



How Atari 
BASIC Works 






-I 



Chapter One 



Atari BASIC: 

A High-Level Language 

Translator 



The programming language which has become the de facto 
standard for the Atari Home Computer is the Atari 8K BASIC 
Cartridge, known simply as Atari BASIC. It was designed to 
serve the programming needs of both the computer novice and 
the experienced programmer who is interested in developing 
sophisticated applications programs. In order to meet such a 
wide range of programming needs, Atari BASIC was designed 
with some unique features. 

In this chapter we will introduce the concepts of high level 
language translators and examine the design features of Atari 
BASIC that allow it to satisfy such a wide variety of needs. 

Language Translators 

Atari BASIC is what is known as a high level language translator. 

A language, as we ordinarily think of it, is a system for 
communication. Most languages are constructed around a set 
of symbols and a set of rules for combining those symbols. 

The English language is a good example. The symbols are 
the words you see on this page. The rules that dictate how to 
combine these words are the patterns of English grammar. 
Without these patterns, communication would be very 
difficult, if not impossible: Out sentence this believe, of make 
don't this trying if sense you to! If we don't use the proper 
symbols, the results are also disastrous: @twu2 yeggopt 
gjsiem, keorw? 

In order to use a computer, we must somehow 
communicate with it. The only language that our machine 
really understands is that strange but logical sequence of ones 
and zeros known as machine language. In the case of the Atari, 
this is known as 6502 machine language. 

When the 6502 central processing unit (CPU) "sees" the 
sequence 01001000 in just the right place according to its rules 
of syntax, it knows that it should push the current contents of 



Chapter One 



the accumulator onto the CPU stack. (If you don't know what 
an "accumulator" or a "CPU stack" is, don't worry about it. 
For the discussion which follows, it is sufficient that you be 
aware of their existence.) 

Language translators are created to make it simpler for 
humans to communicate with computers. There are very few 
6502 programmers, even among the most expert of them, who 
would recognize 01001000 as the push-the-accumulator 
instruction. There are more 6502 programmers, but still not 
very many, who would recognize the hexadecimal form of 
01001000, $48, as the push-the-accumulator instruction. 
However, most, if not all, 6502 programmers will recognize the 
symbol PHA as the instruction which will cause the 6502 to 
push the accumulator. 

PHA, $48, and even 01001000, to some extent, are 
translations from the machine's language into a language that 
humans can understand more easily. We would like to be able 
to communicate to the computer in symbols like PHA; but if 
the machine is to understand us, we need a language translator 
to translate these symbols into machine language. 

The Debug Mode of Atari's Editor/ Assembler cartridge, for 
example, can be used to translate the symbols $48 and PHA to 
the ones and zeros that the machine understands. The 
debugger can also translate the machine's ones and zeros to 
$48 and PHA. The assembler part of the Editor/ Assembler 
cartridge can be used to translate entire groups of symbols like 
PHA to machine code. 

Assemblers 

An assembler — for example, the one contained in the 
Assembler/Editor cartridge — is a program which is used to 
translate symbols that a human can easily understand into the 
ones and zeros that the machine can understand. In order for 
the assembler to know what we want it to do, we must 
communicate with it by using a set of symbols arranged 
according to a set of rules. The assembler is a translator, and 
the language it understands is 6502 assembly language. 

The purpose of 6502 assembly language is to aid program 
authors in writing machine language code. The designers of 
the 6502 assembly language created a set of symbols and rules 
that matches 6502 machine language as closely as possible. 

This means that the assembler retains some of the 



Chapter One 



disadvantages of machine language. For instance, the process 
of adding two large numbers takes dozens of instructions in 
6502 machine language. If human programmers had to code 
those dozens of instructions in the ones and zeros of machine 
language, there would be very few human programmers. 
But the process of adding two large numbers in 6502 
assembly language also takes dozens of instructions. The 
assembly language instructions are easier for a programmer to 
read and remember, but they still have a one-to-one cor- 
respondence with the dozens of machine language 
instructions. The programming is easier, but the process 
remains the same. 

High Level Languages 

High level languages, like Atari BASIC, Atari PILOT, and Atari 
Pascal, are simpler for people to use because they more closely 
approximate human speech and thought patterns. However, 
the computer still understands only machine language. So the 
high level languages, while seeming simple to their users, are 
really much more complex in their internal operations than 
assembly language. 

Each high level language is designed to meet the specific 
need of some group of people. Atari Pascal is designed to 
implement the concept of structured programming. Atari 
PILOT is designed as a teaching tool. Atari BASIC is designed 
to serve both the needs of the novice who is just learning to 
program a computer and the needs of the expert programmer 
who is writing a sophisticated application program, but wants 
the program to be accessible to a large number of users. 

Each of these languages uses a different set of symbols and 
symbol-combining rules. But all these language translators 
were themselves written in assembly language. 

Language Translation Methods 

There are two different methods of performing language 
translation — compilation and interpretation. Languages which 
translate via interpretation are called interpreters. Languages 
which translate via compilation are called compilers. 

Interpreters examine the program source text and simulate 
the operations desired. Compilers translate the program source 
text into machine language for direct machine execution. 



Chapter One 



The compilation method tends to produce faster, more 
efficient programs than does the interpretation method. 
However, the interpretation method can make programming 
easier. 

Problems with the Compiler Method 

The compiler user first creates a program source file on a disk, 
using a text editing program. Then the compiler carefully 
examines the source program text and generates the machine 
language as required. Finally, the machine language code is 
loaded and executed. While this three-step process sounds 
fairly simple, it has several serious "gotchas." 

Language translators are very particular about their 
symbols and symbol-combining rules. If a symbol is 
misspelled, if the wrong symbol is used, or if the symbol is not 
in exactly the right place, the language translator will reject it. 
Since a compiler examines the entire program in one gulp, one 
misplaced symbol can prevent the compiler from 
understanding any of the rest of the program — even though 
the rest of the program does not violate any rules! The result is 
that the user often has to make several trips between the text 
editor and the compiler before the compiler successfully 
generates a machine language program. 

But this does not guarantee that the program will work. If 
the programmer is very good or very lucky, the program will 
execute perfectly the very first time. Usually, however, the user 
must debug the program. 

This nearly always involves changing the source program, 
usually many times. Each change in the source program sends 
the user back to step one: after the text editor changes the 
program, the compiler still has to agree that the changes are 
valid, and then the machine code version must be tested again. 
This process can be repeated dozens of times if the program is 
very complex. 

Faster Programming or Faster Programs? 

The interpretation method of language translation avoids many 
of these problems. Instead of translating the source code into 
machine language during a separate compiling step, the 
interpreter does all the translation while the program is running. 
This means that whenever you want to test the program you're 
writing, you merely have to tell the interpreter to run it. If 
things don't work right, stop the program, make a few 
changes, and run the program again at once. 



Chapter One 



You must pay a few penalties for the convenience of using 
the interpreter's interactive process, but you can generally 
develop a complex program much more quickly than the 
compiler user can. 

However, an interpreter is similar to a compiler in that the 
source code fed to the interpreter must conform to the rules of 
the language. The difference between a compiler and an 
interpreter is that a compiler has to verify the symbols and 
symbol-combining rules only once — when the program is 
compiled. No evaluation goes on when the program is 
running. The interpreter, however, must verify the symbols 
and symbol-combining rules every time it attempts to run the 
program. If two identical programs are written, one for a 
compiler and one for an interpreter, the compiled program will 
generally execute at least ten to twenty times faster than the 
interpreted program. 

Pre-compiling Interpreter 

Atari BASIC has been incorrectly called an interpreter. It does 
have many of the advantages and features of an interpretive 
language translator, but it also has some of the useful features 
of a compiler. A more accurate term for Atari's BASIC 
Language Translator is pre-compiling interpreter. 

Atari BASIC, like an interpreter, has a text editor built into 
it. When the user enters a source line, though, the line is not 
stored in text form, but is translated into an intermediate code, 
a set of symbols called tokens. The program is stored by the 
editor in token form as each program line is entered. Syntax 
and symbol errors are weeded out at that time. 

Then, when you run the program, these tokens are 
examined and their functions simulated; but because much of 
the evaluation has already been done, the execution of an Atari 
BASIC program is faster than that of a pure interpreter. Yet 
Atari BASIC'S program-building process is much simpler than 
that of a compiler. 

Atari BASIC has advantages over compilers and 
interpreters alike. With Atari BASIC, every time you enter a 
line it is verified for language correctness. You don't have to 
wait until compilation; you don't even have to wait until a test 
run. When you type RUN you already know there are no 
syntax errors in your program. 



Chapter Two 



r 

r 



Internal Design 
Overview 



Atari BASIC is divided into two major functional areas: the 
Program Constructor and the Program Executor. The Program 
Constructor is used when you enter and edit a BASIC program. 
The source line pre-compiler, also part of the Program 
Constructor, translates your BASIC program source text lines 
into tokenized lines. The Program Executor is used to execute 
the tokenized program — when you type RUN, the Program 
Executor takes over. 

Both the Program Constructor and the Program Executor 
are designed to use data tables. Some of these tables are 
already contained in BASIC'S ROM (read-only memory). 
Others are constructed by BASIC in the user RAM (random- 
access memory). Understanding these various tables is an 
important key to understanding the design of Atari BASIC. 

Tokens 

In Atari BASIC, tokens are the intermediate code into which 
the source text is translated. They represent source-language 
symbols that come in various lengths — some as long as 100 
characters (a long variable name) and others as short as one 
character (" + " or "-"). Every token, however, is exactly one 
eight-bit byte in length. 

Since most BASIC Language Symbols are more than one 
character long, the representation of a multi-character BASIC 
Language Symbol with a single-byte token can mean a 
considerable saving of program storage space. 

A single-byte token symbol is also easier for the Program 
Executor to recognize than a multi-character symbol, since it 
can be evaluated by machine language routines much more 
quickly. The SEARCH routine — 76 bytes long — located at 
$A462 is a good example of how much assembly language it 
takes to recognize a multi-character symbol. On the other 
hand, the two instructions located at $AB42 are enough to 



Chapter Two 



determine if a one-byte token is a variable. Because routines to 
recognize Atari BASIC'S one-byte tokens take so much less 
machine language, they execute relatively quickly. 

The 256 possible tokens are divided into logical numerical 
groups that also make them simpler to deal with in assembly 
language. For example, any token whose value is 128 ($80) or 
greater represents a variable name. The logical grouping of the 
token values also means faster execution speeds, since, in 
effect, the computer only has to check bit 7 to recognize a 
variable. 

The numerical grouping of the tokens is shown below: 

Token Value (Hex) Description 

00-0D Unused 

0E Floating Point Numeric Constant. 

The next six bytes will hold its value. 

OF String Constant. 

The next byte is the string length. 
A string of that length follows. 

10-3C Operators. 

See table starting at $A7E3 for specific 
operators and values. 

3D-54 Functions. 

See table starting at $A820 for specific 
functions and values. 

55-7F Unused. 

80-FF Variables. 

In addition to the tokens listed above, there is another set 
of single-byte tokens, the Statement Name Tokens. Every 
statement in BASIC starts with a unique statement name, such 
as LET, PRINT, and POKE. (An assignment statement such as 
" A = B + C, " without the word LET, is considered to begin with 
an implied LET.) Each of these unique statement names is 
represented by a unique Statement Name Token. 

The Program Executor does not confuse Statement Name 
Tokens with the other tokens because the Statement Name 
Tokens are always located in the same place in every statement 
— at the beginning. The Statement Name Token value is 
derived from its entry number, starting with zero, in the 
Statement Name Table at $A4AF. 



Chapter Two 



Tables 

A table is a systematic arrangement of data or information. 
Tables in Atari BASIC fall into two distinct types: tables that are 
part of the Atari BASIC ROM and tables that Atari BASIC 
builds in the user RAM area. 

ROM Tables 

The following is a brief description of the various tables in the 
Atari BASIC ROM. The detailed use of these tables will be 
explained in subsequent chapters. 

Statement Name Table ($A4AF). The first two bytes in each 
entry point to the information in the Statement Syntax Table 
for this statement. The rest of the entry is the name of the 
statement name in ATASCII. Since name lengths vary, the last 
character of the statement name has the most significant bit 
turned on to indicate the end of the entry. The value of the 
Statement Name Token is derived from the relative (from zero) 
entry number of the statement name in this table. 
Statement Execution Table ($AA00). Each entry in this table 
is the two-byte address of the 6502 machine language code 
which will simulate the execution of the statement. This table is 
organized with the statements in the same order as the 
statements in the Statement Name Table. Therefore, the 
Statement Name Token can be used as an index to this table. 
Operator Name Table ($A7E3). Each entry comprises the 
ATASCII text of an Operator Symbol. The last character of each 
entry has the most significant bit turned on to indicate the end 
of the entry. The relative (from zero) entry number, plus 16 
($10), is the value of the token for that entry. Each of the entries 
is also given a label whose value is the value of the token for 
that symbol. For example, the ";" symbol at $A7E8 is the fifth 
(from zero) entry in the table. The label for the ";" token is 
CSC, and the value of CSC is $15, or 21 decimal (1*16 + 5). 
Operator Execution Table ($AA70). Each two-byte entry 
points to the address, minus one, of the routine which 
simulates the execution of an operator. The token value, minus 
16, is used to access the entries in this table during execution 
time. The entries in this table are in the same order as in the 
Operator Name Table. 

Operator Precedence Table ($AC3F). Each entry 
represents the relative execution precedence of an individual 
operator. The table entries are accessed by the operator tokens, 



r 



Chapter Two 



minus 16. Entries correspond with the entries in the Operator 
Name Table. (See Chapter 7.) 

Statement Syntax Table ($A60D). Entries in this table are 
used in the process of translating the source program to tokens. 
The address pointer in the first part of each entry in the 
Statement Name Table is used to access the specific syntax 
information for that statement in this table. (See Chapter 5.) 

RAM Tables 

The tables that BASIC builds in the user RAM area will be 

explained in detail in Chapter 3. The following is a brief 

description of these tables: 

Variable Name Table. Each entry contains the source 

ATASCII text for the corresponding user variable symbol in the 

program. The relative (from zero) entry number of each entry 

in this table, plus 128, becomes the value of the token 

representing the variable. 

Variable Value Table. Each entry either contains or points 

to the current value of a variable. The entries are accessed by 

the token value, minus 128. 

Statement Table. Each entry is one tokenized BASIC 

program line. The tokenized lines are kept in this table in 

ascending numerical order by line number. 

Array/String Table. This table contains the current values 

for all strings and numerical arrays. The location of the specific 

values for each string and/or array variable is accessed from 

information in the Variable Value Table. 

Runtime Stack. This is the LIFO Runtime Stack, used to 

control the execution of GOSUB/RETURN and similar 

statements. 

Pre-compiler 

Atari BASIC translates the BASIC source lines from text to 
tokens as soon as they are entered. To do this, Atari BASIC 
must recognize the symbols of the BASIC Language. BASIC 
also requires that its symbols be combined in certain specific 
patterns. If the symbols don't follow the required patterns, 
then Atari BASIC cannot translate the line. The process of 
checking a source line for the required symbol patterns is called 
syntax checking. 

BASIC performs syntax checking as part of the tokenizing 
process. When the Program Editor receives a completed line of 

10 



' 



Chapter Two 



input, the editor hands the line to the syntax routine, which 
examines the first word of the line for a statement name. If a 
valid statement name is not found, then the line is assumed to 
be an implied LET statement. 

The grammatical rules for each statement are contained in 
the Statement Syntax Table. A special section of code examines 
the symbols in the source line, under the direction of the 
grammatical rules set forth in the Statement Syntax Table. If 
the source line does not conform to the rules, then it is reported 
back as an error. Otherwise, the line is translated to tokens. 
The result of this process is returned to the Program Editor for 
further processing. 

Program Editor 

When Atari BASIC is not executing statements, it is in the edit 
mode. When the user enters a source line and hits return, the 
editor accepts the line into a line buffer, where it is examined 
by the pre-compiler. The pre-compiler returns either tokens or 
an error text line. 

If the line started with a line number, the editor inserts the 
tokenized line into the Statement Table. If the Statement Table 
already contains a line with the same line number, then the old 
line is removed from the Statement Table. The new line is then 
inserted just after the statement with the next lower line 
number and just before the statement with the next higher line 
number. 

If the line has no line number, the editor inserts the line at 
the end of the Statement Table. It then passes control to the 
Program Executor, which will carry out the statement(s) in the 
line at the end of the Statement Table. 

Program Executor 

The Program Executor has a pointer to the statement that it is to 
execute. When control is passed to the executor, the pointer 
points to the direct (command) line at the end of the statement 
table. If that statement causes some other line to be executed 
(RUN, GOTO, GOSUB, etc.), the pointer is changed to the 
new line. Lines continue to be executed as long as nothing 
stops that execution (END, STOP, error, etc.). When the 
program execution is stopped, the Program Executor returns 
control to the editor. 

11 



Chapter Two 



When a statement is to be executed, the Statement Name 
Token (the first code in the statement) directs the interpreter to 
the specific code that executes that statement. For instance, if 
that token represents the PRINT statement, the PRINT 
execution code is called. The execution code for each statement 
then examines the other tokens and simulates their operations. 

Execute Expression 

Arithmetic and logical expressions (A + B, C/D + E, F<G, etc.) 
are simulated with the Execute Expression code. Expression 
operators ( + ,-,*, etc.) have execution precedence — some 
operators must be executed before some others. The 
expression 1 + 3*4 has a value of 13 rather than 16 
because * had a higher precedence than + . To properly 
simulate expressions, BASIC rearranges the expression with 
higher precedence first. 

BASIC uses two temporary storage areas to hold parts of 
the rearranged expression. One temporary storage area, the 
Argument Stack, holds arguments — values consisting of 
constants, variables, and temporary values resulting from 
previous operator simulations. The other temporary storage 
area, the Operator Stack, holds operators. Both temporary 
storage areas are managed as Last-In/First-Out (LIFO) stacks. 

LIFO Stacks 

A LIFO (Last In/First Out) stack operates on the principle that 
the last object placed in the stack storage area will be the first 
object removed from it. If the letters A, B, C, and D, in that 
order, were placed in a LIFO stack, then D would be the first 
letter removed, followed by C, B, and A. The operations 
required to rearrange the expression using these stacks will be 
explained in Chapter 7. 

BASIC also uses another LIFO stack, the Runtime Stack, in 
the simulation of statements such as GOSUB and FOR. 
GOSUB requires that BASIC remember where in the statement 
table the GOSUB was located so it will return to the right spot 
when RETURN is executed. If more than one GOSUB is 
executed before a RETURN, BASIC returns to the statement 
after the most recent GOSUB. 



12 



Chapter Three 



Memory Usage 



Many of BASIC'S functions are controlled by a set of tables 
built in RAM not already occupied by BASIC or the Operating 
System (OS). Figure 3.1 is a diagram of memory use by both 
programs. Every time a BASIC programmer enters a statement, 
memory requirements for the RAM tables change. Memory use 
by the OS also varies. Different graphics modes, for example, 
require different amounts of memory. 

These changing memory requirements are monitored, and 
this series of pointers keeps BASIC and the OS from overlaying 
each other in memory: 

• High memory address (HMADR) at location $02E5 

• Application high memory (APHM) at location $000E 

• Low memory address (LMADR) at location $02E7 

When a graphics mode requires larger screen space, the OS 
checks the application high memory address (APHM) that has 
been set by BASIC. If there is enough room for the new screen, 
the OS uses the upper portion of space and sets the pointer 
HMADR to the bottom of the screen to tell the application how 
much space the OS is now using. 

BASIC builds its table toward high memory from low 
memory. The pointer to the lowest memory available to an 
application, called LMADR in the BASIC listing, is set by the 
OS to tell BASIC the lowest memory address that BASIC can 
use. When BASIC needs more room for one of its tables, 
BASIC checks HMADR. If there is enough room, BASIC uses 
the space and puts the highest address it has used into APHM 
for OS. 

BASIC'S operation consists primarily of building, reading, 
and modifying tables. Pointers to the RAM tables are kept in 
consecutive locations in zero page starting at $80. These tables 
are, in order, 

• Multipurpose Buffer 

• Variable Name Table 

• Variable Value Table 

• String/ Array Table 



13 



Chapter Three 



• Statement Table 

• Runtime Stack 

BASIC reserves space for a buffer at LM ADR. It then builds 
the tables contiguously (without gaps), starting at the top of the 
buffer and extending as far as necessary towards APHM. When 
a new entry needs to be added to a table, all data in the tables 
above is moved upward the exact amount needed to fit the new 
entry into the right place. 

Figure 3-1. Memory Usage 



FFFF 

E000 
D800 
D000 

BFFF 
A000 



Operating System 
ROM 



Floating Point 
ROM 



Hardware Registers 



Unused 



BASIC ROM 



Screen 



HMADR 



Free RAM 



0000 



BASIC 
RAM 
Tables 



Operating System 
RAM 



APHM 



LMADR 



14 



Chapter Three 



Variable Name Table 

The Variable Name Table (VNT) is built during the pre-compile 
process. It is read, but not modified, during execution — but 
only by the LIST statement. The VNT contains the names of the 
variables used in the program in the order in which they were 
entered. 

The length of entries in the Variable Name Table depends 
on the length of the variable name. The high order bit of the 
last character of the name is on. For example, the ATASCII code 
for the variable name ABC is 41 42 43 (expressed in 
hexadecimal). In the Variable Name Table it looks like this: 

41 42 C3 

The $ character of a string name and the ( character of an 
array element name are stored as part of the variable name. The 
table entries for variables C, AA$, and X(3) would look like 
this: 

C C3 

AA$ 41 41 A4 
X(3) 58 A8 

It takes only two bytes to store X(3) because this table stores 
onlyX(. 

A variable is represented in BASIC by a token. The value of 
this token is the position (relative to zero) of the variable name 
in the Variable Name Table, plus $80. BASIC references an 
entry in the table by using the token, minus $80, as an index. 
The Variable Name Table is not changed during execution time. 

The zero page pointer to the Variable Name Table is called 
VNTP in the BASIC listing. 

Variable Value Table 

The Variable Value Table (VVT) is also built during the pre- 
compile process. It is both read and modified during execution. 
There is a one-to-one correspondence in the order of entries 
between the Variable Name Table and the Variable Value Table. 
If XXX is the fifth variable in the Variable Name Table, then 
XXX's value is the fifth entry in the Variable Value Table. 
BASIC references a table entry by vising the variable token, 
minus $80, as an index. 

Each entry in the Variable Value Table consists of eight 
bytes. The first two bytes have the following meaning: 



15 



Chapter Three 



1 


2 







type vnum 

type = one byte, which indicates the type of variable 

$00 for floating point variable 

$40 for array variable 

$80 for string variable 
vnum = one byte, which indicates the relative position of the 
variable in the tables 

The meaning of the next six bytes varies, depending on the 
type of variable (floating point, string, or array). In all three 
cases, these bytes are initialized to zero during syntaxing and 
during the execution of the RUN or CLR. 

When the variable is a floating point number, the six bytes 
represent its value. 

When the variable is an array, the remaining six bytes have 
the following format: 



1 


2 


3 4 


5 6 


7 8 






1 
1 


1 
1 


1 

1 



disp 

dim 1 
dim! 



disp diml dim2 

= the two-byte displacement into string/array space of 

this array variable 
= two bytes indicating the first dimension value 
= two bytes indicating the second dimension value 



All three of these values are set appropriately when the array is 
DIMensioned during execution. 

When the variable is a string, the remaining six bytes have 
the following meaning: 



1 


2 


3 4 


5 6 


7 8 






1 

1 


1 
1 


1 
1 



disp curl maxl 



16 



Chapter Three 



disp = the two-byte displacement into string/ array space of 

this string variable. This value is set when the string is 

DIMensioned during execution. 
curl = the two-byte current length of the string. This value 

changes as the length of the string changes during 

execution. 
maxl = the two-byte maximum possible length of this string. 

This value is set to the DIM value during execution. 

When either a string or an array is DIMensioned during 
execution, the low-order bit in the type byte is turned on, so 
that the array type is set to $41 and the string type to $81. 

The zero page pointer to the Variable Value Table is called 
VVTP in the BASIC listing. 

Statement Table 

The Statement Table, built as each statement is entered during 
editing, contains tokenized forms of the statements that were 
entered. This table determines what happens during 
execution. 

The format of a Statement Table entry is shown in Figure 
3-2. There can be several tokens per statement and several 
statements per line. 

Figure 3-2. Format of a Statement Table Entry 



lnum Hen slen snt 



toks eos slen snt 



toks 



eos eol 



lnum = the two-byte line number (low-order, high-order) 
lien = the one-byte line length (the displacement to the next 

line in the table) 
slen = the one-byte statement length (the displacement to 

the next statement in the line) 
snt = the one-byte Statement Name Token 
toks = the other tokens that make up the statement (this 

is variable in length) 
eos = the one-byte end of statement token 
eol = the one-byte end of line token 

The zero page pointer to the Statement Table is called 
STMTAB in the BASIC listing. 

17 



Chapter Three 



String/Array Table 

The String/ Array Table (also called String/ Array Space) is 
created and modified during execution. Strings and arrays can 
be intermixed in the table, but they have different formats. 
Each array or string is pointed to by an entry in the Variable 
Value Table. The entry in the String/ Array Table is created 
when the string or array is DIMensioned during execution. The 
data in the entry changes during execution as the value of the 
string or an element of the array changes. 

An entry in the String/Array Table is not initialized to any 
particular value when it is created. The elements of arrays and 
the characters in a string cannot be counted upon to have any 
particular value. They can be zero, but they can also be garbage 
— data previously stored at those locations. 

Array Entry 

For an array, the String/ Array Table contains one six-byte entry 
for each array element. Each element is a floating point 
number, stored in raveled order. For example, the entry in the 
String/ Array Table for an array that was dimensioned as A(l,2) 
contains six elements, in this order: 

A(0,0) A(0,1) A(0,2) A(1,0) A(l,l) A(l,2) 

String Entry 

A string entry in the String/ Array Table is created during 
execution, when the string is DIMensioned. The size of the 
entry is determined by the DIM value. The "value" of the 
string to BASIC at any time is determined by the data in the 
String/ Array Table and the current length of the string as set in 
the Variable Value Table. 

The zero page pointer to the String/ Array Table is called 
STARP in the BASIC listing. 



The Runtime Stack is created during execution. BASIC uses 
this LIFO stack to control processing of FOR/NEXT loops and 
GOSUBs. When either a FOR or a GOSUB statement is 
encountered during execution, an entry is put on the Runtime 
Stack. When a NEXT, RETURN, or a POP statement is 
encountered, entries are pulled off the stack. 

Both the FOR entry and the GOSUB entry have a four-byte 
header: 

18 



Chapter Three 



type lnum disp 

type = one byte indicating the type of element 
GOSUB type = 
FOR type = non-zero 
lnum = the two-byte number of the line which contains the 

statement (low-order, high-order) 
disp = one byte indicating the displacement into the line in 
the Statement Table of the token which caused this 
stack entry. 

The FOR-type byte is actually the token representing the 
loop control variable from the FOR statement. (In the statement 
FOR I = 1 to 10, 1 is the loop control variable.) So the FOR-type 
byte will have a value of $80 through $FF — the possible values 
of a variable token. 

The FOR entry contains 12 additional bytes, formatted like 
this: 



2 3 4 5 6 



J L 



9 10 11 12 
— I 1 1 



J L 



sval 



step 



sval = the six-byte (floating point) limit value at which to 

stop the loop 
step = the six-byte (floating point) STEP value to increment 

by 

The GOSUB entry consists entirely of the four-byte header. 
The LIST and READ statements also put a GOSUB type entry 
on the Runtime Stack, so that the line containing the LIST or 
READ can be found again when the statement has finished 
executing. 

The zero page pointer to the Runtime Stack is called 
RUNSTK in the BASIC listing. 



19 



Chapter Three 



VNTP 


$82, $83 


VNTD 


$84, $85 


WTP 


$86, $87 


STMTAB 


$88, $89 


STMCUR 


$8A, $8B 


STARP 


$8C, $8D 


RUNSTK 


$8E, $8F 


MEMTOP 


$90, $91 



Zero Page Table Pointers 

The starting addresses of the tables change dynamically during 
both program construction and program execution. BASIC 
keeps the current start addresses of the tables and other 
pointers required to manage memory space in contiguous zero- 
page cells. Each pointer is a two-byte address, low byte first. 

Since these zero page cell addresses remain constant, 
BASIC is always able to find the tables. Here are the zero page 
pointers used in memory management, their names in the 
BASIC listing, and their addresses: 

Multipurpose Buffer 
Variable Name Table 
VNT dummy end 
Variable Value Table 
Statement Table 
Current Statement Pointer 
String/Array Table 
Runtime Stack 
Top of used memory 

Memory Management Routines 

Memory Management routines allocate space to the BASIC 
tables as needed. There are two routines: expand, to add space, 
and contract, to delete space. Each routine has one entry point 
for cases in which the number of bytes to be added or deleted is 
less than 256, and another when it is greater than or equal to 
256. 

The EXPAND and CONTRACT routines often move many 
thousands of bytes each time they are called. The 6502 
microprocessor is designed to move fewer than 256 bytes of 
data very quickly. When larger blocks of data are moved, the 
additional 6502 instructions required can make the process very 
slow. The EXPAND and CONTRACT routines circumvent this 
by using the less-than-256-byte fast-move capabilities in the 
movement of thousands of bytes. The end result is a set of very 
fast and very complex data movement routines. 

All of this complexity does have a drawback. The infamous 
Atari BASIC lock-up problem lives in these two routines. If an 
EXPAND or CONTRACT requires that an exact multiple of 256 
bytes be moved, then the routines move things from the wrong 



20 



Chapter Three 



place in memory to the wrong place in memory, whereupon 
the computer locks up and won't respond. The only way to 
avoid losing hours of work this way is to SAVE to disk or 
cassette frequently. 

EXPAND ($A881) 

Parameters at entry: 

register 

X = the zero page address containing the pointer to 
the location after which space is to be added 

Y = the low-order part of the number of bytes to 

expand 
A = the high-order part of the number of bytes to 
expand 

The routine creates a hole in the table memory, starting at a 
requested location and continuing the requested number of 
bytes. 

The routine first checks to see that there is enough free 
memory space to satisfy the request. 

It adds the requested expand size to each of the zero-page 
table pointers between the one pointed to by the X register and 
MEMTOP. Then each pointer will point to the correct address 
when EXPAND is done. 

EXPAND then creates space at the address indicated by the 
X register. The number of bytes required is contained in the Y 
and A registers. (Y contains the least significant byte, while A 
contains the most significant.) All data from the requested 
address to the address pointed to by MEMTOP is moved 
toward high memory by the requested number of bytes. This 
creates a hole of the proper size. 

The routine then sets Application High Memory (APHM) 
to the value in MEMTOP. This tells the OS the highest memory 
address that BASIC is currently using. 

EXPLOW ($A87F) 
Parameters at entry: 

register 

X = zero page address containing the pointer to the 
location after which space is to be added 

Y = number of bytes to expand (low-order byte only) 



21 



Chapter Three 



This is an additional entry point for the EXPAND routine. It 
is used when the number of bytes to be added to the table is 
less than 256. 

This routine first loads the 6502 accumulator with zero to 
indicate the most significant byte of the expand length. It then 
functions exactly like EXPAND. 

CONTRACT ($A8FD) 

Parameters at entry: 

register 

X = zero page address containing the pointer to the 

starting location where space is to be removed 
Y = the low-order part of the number of bytes to 

contract 
A = the high-order part of the number of bytes to 

contract 

This routine removes a requested number of bytes at a 
requested location by moving all the data from higher in the 
tables downward the exact amount needed to replace the 
unwanted bytes. 

It subtracts the requested contract size from each of the 
zero page table pointers between the one pointed to by the X 
register and MEMTOP. Then each pointer will point to the 
correct address when CONTRACT is done. 

The routine sets application high memory (APHM) to the 
value in MEMTOP to indicate to the OS the highest memory 
address that BASIC is currently using. 

The block of data to be moved downward is defined by 
starting at the address pointed to by the zero-page address 
pointed to in X, plus the offset number stored in Y and A, and 
then continuing to the address specified at MEMTOP. Each 
byte of data in that block is moved downward in memory by 
the number of bytes specified in Y and A, effectively erasing all 
the data between the specified address and that address plus 
the requested offset. 

CONTLOW ($A8FB) 

Parameters at entry: 

register 

X = the zero page address containing the pointer to 
the location at which space is to be removed 



22 



Chapter Three 



Y = the number of bytes to contract (low-order byte 
only) 

This routine is used to remove fewer than 256 bytes from 
the tables at a requested location by moving all the data from 
higher in the tables downward the exact amount needed to 
replace the unwanted bytes. 

This routine first loads the 6502 accumulator with zero to 
serve as the most significant byte of the contract length. It then 
functions exactly like CONTRACT. 

Miscellaneous Memory Allocations 

Besides the tables, which change dynamically, BASIC also uses 
buffers and stacks at fixed locations. 

The Argument/Operator Stack is allocated at BASIC'S low 
memory address and occupies 256 bytes. During pre-compiling 
it is used as the output buffer for the tokens. During execution, 
it is used while evaluating an expression. This buffer/stack is 
referenced by a pointer at location $80. This pointer has several 
names in the BASIC listing: LOMEM, ARGOPS, ARGSTK, 
and OUTBUFF. 

The Syntax Stack is used during the process of syntaxing a 
statement. It is referenced directly — that is, not through a 
pointer. It is located at $480 and is 256 bytes long. 

The Line Buffer is the storage area where the statement is 
placed when it is ENTERed. It is the input buffer for the edit 
and pre-compile processes. It is 128 bytes long and is 
referenced directly as LBUFF. Often the address of LBUFF is 
also put into INBUFF so that the buffer can be referenced 
through a pointer, though INBUFF can point to other locations 
during various phases of BASIC'S execution. 



23 



Chapter Four 



Program Editor 



The Atari keyboard is the master control panel for Atari BASIC. 
Everything BASIC does has its origins at this control panel. The 
Program Editor's job is to service the control panel and respond 
to the commands that come from it. 

The editor gets a line from the user at the keyboard; does 
some preliminary processing on the line; passes the line to the 
pre-compiler for further processing; inserts, deletes, or 
replaces the line in the Statement Table; calls the Program 
Executor when necessary; and then waits to receive the user's 
next line input. 

Line Processing 

The Program Editor, which starts at $A060, begins its process 
by resetting the 6502 CPU stack. Resetting the CPU stack is a 
drastic operation that can only occur at the beginning of a 
logical process. Each time Atari BASIC prepares to get a new 
line from the user, it restarts its entire logical process. 

Getting a Line 

The Program Editor gets a user's line by calling CIO. The origin 
of the line is transparent to the Program Editor. The line may 
have been typed in at the keyboard or entered from some 
external device like the disk (if the ENTER command was 
given). The Program Editor simply calls CIO and asks it to put a 
line of not more than 255 bytes into the buffer pointed to by 
INBUFF ($F3). INBUFF points to the 128-byte area defined at 
LBUFF($580). 

The OS's screen editor, which is involved in getting a line 
from the keyboard, will not pass BASIC a line that is longer 
than 120 bytes. Normally, then, the 128-byte buffer at LBUFF is 
big enough to contain the user's line. 

Sometimes, however, if a line was originally entered from 
the keyboard with few blanks and many abbreviations, then 
LISTed to and re-ENTERed from the disk, an input line may be 
longer than 128 bytes. When this happens, data in the $600 
page is overlaid. A LINE TOO LONG error will not necessarily 



25 



r 



Chapter Four 



occur at this point. A LINE TOO LONG error occurs only if the 
Pre-compiler exceeds its stack while processing the line or if 
the tokenized line OUTBUFF exceeds 256 bytes. These 
overflows depend on the complexity of the line rather than on 
its actual length. 

When CIO has put a line into the line buffer (LBUFF) and 
the Program Editor has regained control, it checks to see if the 
user has changed his mind and hit the break key. If the user did 
indeed hit break, the Program Editor starts over and asks CIO 
for another line. 

Flags and Indices 

In order to help control its processing, the Program Editor uses 
flags and indices. These must be given initial values. 

CIX and COX. The index CIX ($F2) is used to access the user's 
input line in the line buffer (LBUFF), while COX ($94) is used to 
access the tokenized statement in the output buffer 
(OUTBUFF). These buffers and their indices are also used by 
the pre-compiler. The indices are initialized to zero to indicate 
the beginning of the buffers. 

DIRFLG. This flag byte ($A6) is used by the editor to remember 
whether a line did or did not have a line number, and also to 
remember if the pre-compiler found an error in that line. 
DIRFLG is initialized to zero to indicate that the line has a line 
number and that the pre-compiler has not found an error. 

MAXCIX. This byte ($9F) is maintained in case the line contains 
a syntax error. It indicates the displacement into LBUFF of the 
error. The character at this location will then be displayed in 
inverse video. The Program Editor gives this byte the same 
initial value as CIX, which is zero. 

SWNTP. The pointer to the current top of the Variable Name 
Table (VNTD) is saved as SWNTP ($AD) so that if there is a 
syntax error in this line, any variables that were added can be 
removed. If a user entered an erroneous line, such as 100 
A = XAND B, the variable XAND would already have been 
added to the variable tables before the syntax error was 
discovered. The user probably meant to enter 100 A = X AND B, 
and, since there can only be 128 variables in BASIC, he 
probably does not want the variable XAND using up a place in 
the variable tables. The Program Editor uses SWNTP to find 
the entry in the Variable Name Table so it can be removed. 

26 



Chapter Four 



SVVVTE. The process used to indicate which variable entries to 
remove from the Variable Value Table in case of error is 
different. The number of new variables in the line 
(SVWTE,$B1) is initialized to zero. The Program Pre-compiler 
increments the value every time it adds a variable to the 
Variable Value Table. If a syntax error is detected, this number 
is multiplied by eight (the number of bytes in each entry on the 
Variable Value Table) to get the number of bytes to remove, 
counting backward from the most recent value entered. 

Handling Blanks 

In many places in the BASIC language, blanks are not 
significant. For example, 

100 IFX = 6THENGOTO500 

has the same meaning as 

100 IF X = 6 THEN GOTO 500. 

The Program Editor, using the SKIPBLANK routine 
($DBA1), skips over unnecessary blanks. 

Processing the Line Number 

Once the editor has skipped over any leading blanks, it begins 
to examine the input line, starting with the line number. The 
floating point package is called to determine if a line number is 
present, and, if so, to convert the ATASCII line number to a 
floating point number. The floating point number is converted 
to an integer, saved in TSLNUM for later use, and stored in the 
tokenized line in the output buffer (OUTBUFF). 

The routine used to store data into OUTBUFF is called 
:SETCODE ($A2C8). When :SETCODE stores a byte into 
OUTBUFF, it also increments COX, that buffer's index. 

BASIC could convert the ATASCII line number directly to 
an integer, but the routine to do this would not be used any 
other time. Routines to convert ATASCII to floating point and 
floating point to integer already exist in BASIC for other 
purposes. Using these existing routines conserves ROM space. 

An interesting result of this sequence is that it is valid to 
enter a floating point number as a line number. For example, 
100.1, 10.9, or 2.05E2 are valid line numbers. They would be 
converted to 100, 11, and 205 respectively. 

If the input line does not start with a line number, the line 
is considered to be a direct statement. DIRFLG is set to $80 so 



27 



Chapter Four 



that the editor can remember this fact. The line number is set to 
32768 ($8000). This is one larger than the largest line number a 
user is allowed to enter. BASIC later makes use of this fact in 
processing the direct statement. 

Line length. The byte after the line number in the tokenized 
line in OUTBUFF is reserved so that the line length (actually 
the displacement to the next line) can be inserted later. (See 
Chapter 2.) The routine :SETCODE is called to reserve the byte 
by incrementing (COX) to indicate the next byte. 

Saving erroneous lines. In the byte labeled STMSTRT, the 
Program Editor saves the index into the line buffer (LBUFF) of 
the first non-blank character after the line number. This index 
is used only if there is a syntax error, so that all the characters 
in the erroneous line can be moved into the tokenized line 
buffer and from there into the Statement Table. 

There are advantages to saving an erroneous line in the 
Statement Table, because you can LIST the error line later. The 
advantage is greatest, not when entering a program at the 
keyboard, but when entering a program originally written in a 
different BASIC on another machine (via a modem, perhaps). 
Then, when a line that is not correct in Atari BASIC is entered, 
the line is flagged and stored — not discarded. The user can 
later list the program, find the error lines, and re-enter them 
with the correct syntax for Atari BASIC. 

Deleting lines. If the input line consists solely of a line number, 
the Program Editor deletes the line in the Statement Table 
which has that line number. The deletion is done by pointing to 
the line in the Statement Table, getting its length, and calling 
CONTRACT. (See Chapter 3.) 

Statement Processing 

The user's input line may consist of one or more statements. 
The Program Editor repeats a specific set of functions for each 
statement in the line. 

Initializing 

The current index (COX) into the output buffer (OUTBUFF) is 
saved in a byte called STMLBD. A byte is reserved in 
OUTBUFF by the routine :SETCODE. Later, the value in 



28 



Chapter Four 



STMLBD will be used to access this byte, and the statement 
length (the displacement to the next statement) will be stored 
here. 

Recognizing the Statement Name 

After the editor calls SKBLANK to skip blanks, it processes the 
statement name, now pointed to by the input index (CIX). The 
editor calls the routine SEARCH ($A462) to look for this 
statement name in the Statement Name Table. SEARCH saves 
the table entry number of this statement name into location 
STENUM. 

The entry number is also the Statement Name Token value, 
and it is stored into the tokenized output buffer (OUTBUFF) as 
such by :SETCODE. The SEARCH routine also saves the 
address of the entry in SRC ADR for use by the pre-compiler. 

If the first word in the statement was not found in the 
Statement Name Table, the editor assumes that the statement 
is an implied LET, and the appropriate token is stored. It is left 
to the pre-compiler to determine if the statement has the 
correct syntax for LET. 

The editor now gives control to the pre-compiler, which 
places the appropriate tokens in OUTBUFF, increments the 
indices CIX and COX to show current locations, and indicates 
whether a syntax error was detected by setting the 6502 carry 
flag on if there was an error and clearing the carry flag if there 
was not. (See Chapter 5.) 

If a Syntax Error Is Detected 

If the 6502 carry flag is set when the editor regains control, the 
editor does error processing. 

In MAXCIX, the pre-compiler stored the displacement 
into LBUFF at which it detected the error. The Program Editor 
changes the character at this location to inverse video. 

The character in inverse video may not be the point of error 
from your point of view, but it is where the pre-compiler 
detected an error. For example, assume you entered X = YAND 
Z. You probably meant to enter X = Y AND Z, and therefore 
would consider the error to be between Y and AND. However, 
since YAND is a valid variable name, X = YAND is a valid 
BASIC statement. 

The pre-compiler doesn't know there is an error until it 
encounters B. The value of highlighting the error with inverse 



29 



Chapter Four 



video is that it gives the user an approximation of where the 
error is. This can be a big advantage, especially if the input line 
contained multiple statements or complex expressions. 

The next thing the editor does when a syntax error has 
been detected is set a value in DIRFLG to indicate this fact for 
future reference. Since the DIRFLG byte also indicates whether 
this is a direct statement, the error indicator of $40 is ORed with 
the value already in DIRFLG. 

The editor takes the value that it saved in STMSTRT and 
puts it into CIX so that CIX now points to the start of the first 
statement in the input line in LBUFF. STMLBD is set to indicate 
the location of the first statement length byte in OUTBUFF. (A 
length will be stored into OUTBUFF at this displacement at a 
later time.) 

The editor sets the index into OUTBUFF (COX) to indicate 
the Statement Name Token of the first statement in OUTBUFF, 
and stores a token at that location to indicate that this line has a 
syntax error. The entire line (after the line number) is moved 
into OUTBUFF. At this point COX indicates the end of the line 
in OUTBUFF. (Later, the contents of OUTBUFF will be moved 
to the Statement Table.) 

This is the end of the special processing for an erroneous 
line. The process that follows is done for both correct and 
erroneous lines. 

Final Statement Processing 

During initial line processing, the Program Editor saved in 
STMLBD a value that represents the location in OUTBUFF at 
which the statement length (displacement to the next 
statement) should be stored. The Program Editor now retrieves 
that value from STMLBD. Using this value as an index, the 
editor stores the value from COX in OUTBUFF as the 
displacement to the next statement. 

The Program Editor checks the next character in LBUFF. If 
this character is not a carriage return (indicating end of the 
line), then the statement processing is repeated. When the 
carriage return is found, COX will be the displacement to the 
next line. The Program Editor stores COX as the line length at a 
displacement of two into OUTBUFF. 



30 



Chapter Four 



Statement Table Processing 

The final tokenized form of the line exists in OUTBUFF at this 
point. The Program Editor's next task is to insert or replace the 
line in the Statement Table. 

The Program Editor first needs to create the correct size 
hole in the Statement Table. The editor calls the GETSTMT 
routine ($A9A2) to find the address where this line should go 
in the Statement Table. If a line with the same line number 
already exists, the routine returns with the address in 
STMCUR and with the 6502 carry flag off. Otherwise, the 
routine puts the address where the new line should be inserted 
in the Statement Table into STMCUR and turns on the 6502 
carry flag. (See Chapter 6.) 

If the line does not exist in the Statement Table, the editor 
loads zero into the 6502 accumulator. If the line does exist, the 
editor calls the GETLL routine ($A9DD) to put the line length 
into the accumulator. The editor then compares the length of 
the line already in the Statement Table (old line) with the 
length of the line in OUTBUFF (new line). 

If more room is needed in the Statement Table, the editor 
calls the EXPLOW ($A87F; see Chapter 3). If less space is 
needed for the new line, it calls a routine to point to the next 
line (GNXTL, at location $A9D0; see Chapter 6), and then calls 
the CONTLOW ($A8FB; see Chapter 3). 

Now that we have the right size hole, the tokenized line is 
moved from OUTBUFF into the Statement Table at the location 
indicated by STMCUR. 

Line Wrap-up 

After the line has been added to the Statement Table, the editor 
checks DIRFLG for the syntax error indicator. If the second 
most significant bit ($40) is on, then there is an error. 

Error Wrap-up 

If there is an error, the editor removes any variables that were 
added by this line by getting the number of bytes that were 
added to the Variable Name Table and the Variable Value Table 
from SWNTP and SWVTE. It then calls CONTRACT ($A8FD) 
to remove the bytes from each table. 

Next, the editor lists the line. The Statement Name Token, 
which was set to indicate an error, causes the word "ERROR" 



31 



Chapter Four 



to be printed. An inverse video character indicates where the 
error was detected. The editor now waits for you to enter 
another line. 

Handling Correct Lines 

If the line was syntactically correct, the editor again examines 
DIRFLG. In earlier processing, the most significant bit ($80) of 
this byte was set on if the line was a direct statement. If it is not 
a direct statement, then the editor is finished with the line, and 
it waits for another input line. 

If the line is a direct statement, earlier processing already 
assigned it a line number of 32768 ($8000), one larger than the 
largest line number a user can enter. Since lines are arranged in 
the Statement Table in ascending numerical order, this line will 
have been inserted at the end of the table. The current 
statement pointer (STMCUR— $8A, $8B) points to this line. 

The Program Editor transfers control to a Program Executor 
routine, Execution Control (EXECNL at location $A95F), which 
will handle the execution of the direct statement. (See 
Chapter 6.) 



32 



Chapter Five 



The Pre-compiler 



The symbols and symbol-combining rules of Atari BASIC are 
coded into Syntax Tables, which direct the Program Pre- 
compiler in examining source code and producing tokens. The 
information in the Syntax Tables is a transcription of a meta- 
language definition of Atari BASIC. 

The Atari BASIC Meta-language 

A meta-language is a language which describes or defines 
another language. Since a meta-language is itself a language, it 
also has symbols and symbol-combining rules — which define 
with precision the symbols and symbol-combining rules of the 
subject language. 

Atari BASIC is precisely defined with a specially developed 
meta-language called the Atari BASIC Meta-language, or 
ABML. (ABML was derived from a commonly used compiler- 
technology meta-language called BNF.) The symbols and 
symbol-combining rules of ABML were intentionally kept very 
simple. 

Making Up a Language 

To show you how ABML works, we'll create an extremely 
simple language called SAP, for Simple Arithmetic Process. 
SAP symbols consist of variables, constants, and operators. 

• Variables: The letters A, B, and C only. 

• Constants: The numbers 1,2,3,4,5,6,7,8, and 9 only. 

• Operators: The characters +,-,*, /, and ! only. Of 

course, you already know the functions of all 
the operators except "!". The character ! is a 
pseudo-operator of the SAP language used 
to denote the end of the expression, like the 
period that ends this sentence. 

The grammar of the SAP language is precisely defined by 
the ABML definition in Figure 5-1. 



33 



Chapter Five 



Figure 5-1. The SAP Language Expressed in ABML 



SAP 

< expression > 

< operation > 

< value > 

< constant > 
< variable > 

< operator > 



< expression > ! 

< value > < operation > | 

< operator > < expression > 

< constant > | < variable > 

1|2|3|4|5|6|7|8|9 
A I B I C 



+ 



/ 



The ABML symbols used to define the SAP language in Figure 
5-1 are: 



: = is defined as 



or 



< > label 



terminal 
symbols 



Whatever is on the left of : = is defined as 
consisting of whatever is on the right of : = , 
and in that order. 

The symbol | allows choices for what 
something is defined as. For instance, in the 
sixth line < variable > can be A or B or C. 
If | does not appear between two symbols, 
then there is no choice. For example, in the 
second line < expression > must have both 
< value > and < operation >, in that order, 
to be valid. 

Whatever comes between < and > is an 
ABML label. All labels, as non-terminal 
symbols, must be defined at some point, 
though the definitions can be circular — 
notice that < operation > is part of the 
definition of < expression > in the second 
line, while in the third line < expression > 
is part of the definition of < operation > . 
Symbols used in definitions, which are not 
enclosed by < and > and are also not one 
of the ABML symbols, are terminal symbols 
in the language being defined by ABML. In 
SAP, some terminal symbols are A, !, B, *, 
and 1. They cannot be defined as consisting 
of other symbols — they are themselves the 
symbols that the SAP language manipu- 



34 



Chapter Five 



lates, and must appear exactly as they are 
shown to be valid in SAP. In effect, they are 
the vocabulary of the SAP language. 

Statement Generation 

The ABML description of SAP can be used to generate 
grammatically correct statements in the SAP language. To do 
this, we merely start with the first line of the definition and 
replace the non-terminal symbols with the definitions of those 
symbols. The replacement continues until only terminal 
symbols remain. These remaining terminal symbols constitute 
a grammatically correct SAP statement. 

Since the or statement requires that one and only one of the 
choices be used, we will have to arbitrarily replace the non- 
terminal with the one valid choice. 

Figure 5-2 illustrates the ABML statement generation 
process. 

Figure 5-2. The Generation of One Possible SAP 
Statement 



(J) 


SAP : 


(2) 


SAP : 


(3) 


SAP : 


(4) 


SAP : 


(5) 


SAP : 


(6) 


SAP : 


(7) 


SAP : 


(8) 


SAP : 


(9) 


SAP : 


(10) 


SAP : 


(11) 


SAP 


(12) 


SAP 


(13) 


SAP 


(14) 


SAP 


(15) 


SAP 



< expression > ! 

< value > < operation > ! 

< variable > < operation > ! 
B < operation > ! 

B < operator > < expression > ! 

B*< expression > ! 

B* < value > < operation > ! 

B* < constant > < operation > ! 

B*4< operation > ! 

B*4 < operator > < expression > ! 

B*4 + < expression > ! 

B*4 + < value > < operation > ! 

B*4+ < variable > < operation >! 

B*4 + C < operation > ! 

B*4 + C! 



~ 



In (2), < value >< operation > replaces < expression > 
because the ABML definition of SAP (Figure 5-1) defines 
< expression > as < value > < operation >. 

In (3), the non-terminal < value > is replaced with 



35 



Chapter Five 



< variable > . The definition of < value > gives two choices for 
the substitution of < value > . We happened to choose 

< variable > . 

In (4), we reach a terminal symbol, and the process of 
defining < value > ends. We happened to choose B to replace 

< variable > . 

In (5), we go back and start defining < operation > . There 
are two choices for the replacement of < operation > , either 

< operator > < expression > or nothing at all (since there is 
nothing to the right of I in the second line of Figure 5-1). If 
nothing had been chosen, then (5) would have been: SAP : =B! 
The statement B! has no further non-terminals; the process 
would have been finished, and a valid statement would have 
been produced. Instead we happened to choose 

< operator > < expression > . 

The SAP definition for < expression > is 

< value > < operation > . If we replace < operation > with its 
definition we get: 

< expression > : = < value > < operator > < expression > 

The definition of < expression > includes < expression > 
as part of its definition. If the < operator > < expression > 
choice were always made for < operation > , then the process 
of replacement would never stop. A SAP statement can be 
infinitely long by definition. The only thing which prevents us 
from always having an infinitely long SAP statement is that 
there is a second choice for the replacement of < operation > : 
nothing. 

The replacements in (5) and (10) reflect the repetitive 
choices of defining < expression > in terms of itself. The choice 
in (15) reflects the nothing choice and thus finishes the 
replacement process. 

Computerized Statement Generation 

If we slightly modify our procedure for generating statements, 
we will have a process that could be easily programmed into a 
computer. Instead of arbitrarily replacing the definition of non- 
terminals, we can think of the non-terminal as a GOSUB. 
When we see <X> :=<Y><Z>,we can think of < Y > as 
being a subroutine-type procedure: 

(a) Go to the line that has < Y > on the left side . 

(b) Process the definition (right side) of < Y > . 



36 



Chapter Five 



(c) If while processing the definition of < Y > , other non- 
terminals are found, GOSUB to them. 

(d) If while processing the definition of < Y > we 
encounter a terminal, output the terminal symbol as the 
next symbol of the generated statement. 

(e) When the definition of < Y > is finished, return to the 
place that < Y> was called from and continue. 

Since ABML is structured so that it can be programmed, a 
fascinating exercise is to design a simple English sentence 
grammar with ABML, then write a BASIC program to generate 
valid English sentences at random. The randomness of the 
sentences would be derived by using the RND function to 
select from the definitions or choices. An example of such a 
grammar is shown in Figure 5-3. (The programming exercise is 
left to you.) 

Figure 5-3. A Simple English Sentence Grammar in ABML 

SENTENCE : = < subject > < adverb > < verb > < object > . 

< subject > : = The < adjective > < noun > 

< verb > : = eats | sleeps | drinks | talks | hugs 

< adverb > : = quickly | silently | slowly | viciously | 

lovingly f sadly | 
< object > := at home | in the car | at the table | at 

school | < subject > 
<noun> := boy | girl | dog | programmer | computer 
| teacher 
< adjective > := happy | sad | blue | light | round | smart 
| cool | nice | 

Syntactical Analysis 

The process of examining a language statement for 
grammatical correctness is called syntactical analysis, or 
syntaxing. 

Statement verification is similar to statement generation. 
Instead of arbitrarily choosing which or definition to use, 
however, the choices are already made, and we must check to 
see whether the statement symbols are used in valid patterns. 
To do this, we must process through each or definition until we 
find a matching valid terminal symbol. 

The result of statement generation is a valid, grammatically 
correct statement, but the result of statement verification is a 

37 



Chapter Five 



statement validity indication, which is a simple yes or no. Either 
the statement is grammatically correct or it is not. Failure 
occurs when some statement symbol cannot be matched with a 
valid terminal symbol under the rules of the grammar. 

The Reporting System 

To use the pass/fail result of statement verification, we must 
build a reporting system into the non-terminal checking 
process. Whenever we, in effect, GOSUB to a non-terminal 
definition, that non-terminal definition must report its pass/fail 
status. 

A fail status is generated and returned by a non-terminal 
definition when it finds no matching terminal for the current 
statement symbol. If the current statement symbol is B and the 

< constant > definition in the SAP language is called, then 

< constant > would report a fail status to the routine that 
called it. 

A pass status is returned when a terminal symbol is found 
which matches the current statement symbol. If our current 
statement symbol had been 7 instead of B, then < constant > 
would have reported pass. 

Whenever such a match does occur, we return to the 
statement, and the next symbol to the right becomes the new 
current symbol for examination and verification. 

Cycling Through the Definitions 

In SAP, the < constant > definition is called from the < value > 
definition. If < constant > reports fail, then we examine the 
next or choice, which is < variable > . The current symbol is B, 
so < variable > reports pass. 

Since at least one of the or choices of < value > has 
reported pass, < value > will report pass to its caller. If both 

< constant > and < variable > had reported fail, then 

< value > would report fail to its caller. 

The caller of < value > is < expression > . If < value > 
reports pass, < operation > is called. If < operation > reports 
pass, then < expression > can report pass to its caller. If either 

< value > or < operation > reports fail, then < expression > 
must report fail, since there are no other or choices for 

< expression > . 

The definition of < operation > contains a special pass/ fail 
property. If either < operator > or < expression > reports fail, 



38 



Chapter Five 



then the or choice must be examined. In this case the or choice 
is nothing. The or nothing means something special: report pass, 
but do not advance to the next symbol. 

The final pass/fail report is generated from the first line of 
the definition. If < expression > reports pass and the next 
symbol is !, then SAP reports pass. If either one of these 
conditions has a fail status, then SAP must report fail to 
whatever called SAP from outside the language. 

Backing Up 

Sometimes it is necessary to back up over symbols which have 
already been processed. Let's assume that there was a 
definition of the type <X> : = <Y>|<Z>.Itis possible that 
while < Y > is attempting to complete its definition, it will find 
a number of valid matching terminal symbols before it 
discovers a symbol that it cannot match. In this case, < Y > 
would have consumed a number of symbols before it decided 
to report fail. All of the symbols that < Y > consumed must be 
unconsumed before <Z> can be called, since <Z> will need 
to check those same symbols. 

The process of unconsuming symbols is called backup. 
Backup is usually performed by the caller of < Y > , which 
remembers which source symbol was current when it called 
< Y > . If < Y > reports fail, then the caller of < Y > restores the 
current symbol pointer before calling < Z > . 

Locating Syntax Error 

When a final report oifail is given for a statement, it is often 
possible to guess where the error occurred. In a left-to-right 
system, the symbol causing the failure is usually the symbol 
which follows the rightmost symbol found to be valid. If we 
keep track of the rightmost valid symbol during the various 
backups, we can report a best guess as to where the failure- 
causing error is located. This is exactly what Atari BASIC does 
with the inverse video character in the ERROR line. 

For simplicity, our example was coded for SAP, but the 
syntactical analysis we have just described is essentially the 
process that the Atari BASIC pre-compiler uses to verify the 
grammar of a source statement. The Syntax Tables are an 
ABML description of Atari BASIC. The pre-compiler, also 
known as the syntaxer, contains the routines which verify 
BASIC statements. 



39 



Chapter Five 



Statement Syntax Tables 

There is one entry in the Syntax Tables for each BASIC 
statement. Each statement entry in the Syntax Table is a 
transcription of an ABML definition of the grammar for that 
particular statement. The starting address of the table entry for 
a particular statement is pointed to by that statement's entry in 
the Statement Name Table. 

The data in the Syntax Tables is very much like a computer 
machine language. The pseudo-computer which executes this 
pseudo-machine language is the pre-compiler code. Like any 
machine language, the pseudo-machine language of the Syntax 
Tables has instructions and instruction operands. For example, 
an ABML non-terminal symbol is transcribed to a code which 
the pre-compiler executes as a type of "GO SUB and report 
pass/fail" command. 

Here are the pseudo-instruction codes in the Syntax Tables; 
each is one byte in length. 

Absolute Non-Terminal Vector 

Name: ANTV 
Code: $00 

This is one of the forms of the non-terminal GOSUB. It is 
followed by the address, minus 1, of the non-terminal's 
definition within the Syntax Table. The address is two bytes 
long, with the least significant byte first. 

External Subroutine Call 

Name: ESRT 
Code: $01 

This instruction is a special type of terminal symbol 
checker. It is followed by the address, minus 1, of a 6502 
machine language routine. The address is two bytes long, with 
the least significant byte first. The ESRT instruction is a dens ex 
machina — the "god from the machine" who solved 
everybody's problems at the end of classical Greek plays. 
There are some terminals whose definition in ABML would be 
very complex and require a great many instructions to describe. 
In these cases, we go outside the pseudo-machine language of 
the Syntax Tables and get help from 6502 machine language 
routines — the dens ex machina that quickly gives the desired 



40 



Chapter Five 



result. A numeric constant is one example of where this outside 
help is required. 

ABML or 

Name: OR 
Value: $02 

This is the familiar ABML or symbol ( | ). It provides for an 
alternative definition of a non-terminal. 

Return 

Name: RTN 
Value: $03 

This code signals the end of an ABML definition line. 
When we write an ABML statement on paper, the end of a 
definition line is obvious — there is no further writing on the 
line. When ABML is transcribed to machine codes, the 
definitions are all pushed up against each other. Since the 
function that is performed at the end of a definition is a return, 
the end of definition is called return (RTN). 

Unused (Codes $04 through $0D are unused.) 

Expression Non-Terminal Vector 

Name: VEXP 
Value: $0E 

The ABML definition for an Atari BASIC expression is 
located at $A60D. Nearly every BASIC statement definition 
contains the possibility of having < expression > as part of it. 
VEXP is a single-byte call to < expression > , to avoid wasting 
the two extra bytes that ANTV would take. The pseudo- 
machine understands that this instruction is the same as an 
ANTV call to < expression > at$A60D. 

Change Last Token 

Name: CHNG 
Value: $0F 

This instruction is followed by a one-byte change to token 
value. The operator token instructions cause a token to be 
placed into the output buffer. Sometimes it is necessary to 
change the token that was just produced. For example, there 
are several = operators. One = operator is for the assignment 



41 



Chapter Five 



statement LET X = 4. Another = operator is for comparison 
operations like IF Y = 5. The pseudo-machine will generate the 
assignment = token when it matches = . The context of the 
grammar at that point may have required a comparison = token. 
The CHNG instruction rectifies this problem. 

Operator Token 

Name: (many) 

Value: $10 through $7F 

These instructions are terminal codes for the Atari BASIC 
Operators. The code values are the values of each operator 
token. The values, value names, and operator symbols are 
defined in the Operator Name Table (see Chapter 2). 

When the pseudo-machine sees these terminal symbol 
representations, it compares the symbol it represents to the 
current symbol in the source statement. If the symbols do not 
match, then/fl/7 status is generated. If the symbols match, then 
pass status is generated, the token (instruction value) is placed 
in the token output buffer, and the next statement source 
symbol becomes the current symbol for verification. 

Relative Non-Terminal Vectors 

Name: (none) 

Value: $80 - $BF (Plus) 

$C0 - $FF (Minus) 

This instruction is similar to ANTV, except that it is a single 
byte. The upper bit is enough to signal that this one-byte code 
is a non-terminal GOSUB. The destination address of the 
GOSUB is given as a position relative to the current table 
location. The values $80 through $BF correspond to an address 
which is at the current table address plus $00 through $3F. The 
values $C0 through $FF correspond to an address which is at 
the current table address minus $01 through $3F. 

Pre-compiler Main Code Description 

The pre-compiler, which starts at SYNENT ($A1C3), uses the 
pseudo-instructions in the Syntax Tables to verify the 
correctness of the source line and to generate the tokenized 
statements. 



42 



Chapter Five 



Syntax Stack 

The pre-compiler uses a LIFO stack in its processing. Each time 
a non-terminal vector ("GOSUB") is executed, the pre- 
compiler must remember where the call was made from. It 
must also remember the current locations in the input buffer 
(source statement) and the output buffer (tokenized statement) 
in case the called routine reports fail and backup is required. 
This LIFO stack is called the Syntax Stack. 

The Syntax Stack starts at $480 at the label SIX. The stack is 
256 bytes in size. Each entry in the stack is four bytes long. The 
stack can hold 64 levels of non-terminal calls. If a sixty-fifth 
stack entry is attempted, the LINE TOO LONG error is 
reported. (This error should be called LINE TOO COMPLEX, 
but the line is most likely too long also.) 

The first byte of each stack entry is the current input index 
(CIX). The second byte is the current output index (COX). The 
final two bytes are the current address within the syntax tables. 

The current stack level is managed by the STKLVL ($A9) 
cell. STKLVL maintains a value from $00 to $FC, which is the 
displacement to the current top of the stack entry. 

Initialization 

The editor has saved an address in SRC ADR ($96). This 
address is the address, minus 1, of the current statement's 
ABML instructions in the Syntax Tables. The current input 
index (CIX) and the current output index (COX) are also preset 
by the editor. 

The initialization code resets the syntax stack manager 
(STKLVL) to zero and loads the first stack entry with the values 
in CIX, COX, and CPC — the current program counter, which 
holds the address of the next pseudo-instruction in the Syntax 
Tables. 

PUSH 

Values are placed on the stack by the PUSH routine ($A228). 
PUSH is entered with the new current pseudo-program 
counter value on the CPU stack. PUSH saves the current CIX, 
COX, and CPC on the syntax stack and increments STKLVL. 
Next, it sets a new CPC value from the data on the CPU stack. 
Finally, PUSH goes to NEXT. 



43 



Chapter Five 



POP 

Values are removed from the stack with the POP routine 
($A252). POP is entered with the 6502 carry flag indicating 
pass/fail. If the carry is clear, then pass is indicated. If the carry is 
set, then/flf/ is indicated. 

POP first checks STKLVL. If the current value is zero, then 
the pre-compiler is done. In this case, POP returns to the editor 
via RTS. The carry bit status informs the editor of the pass/ fail 
status. 

If STKLVL is not zero, POP decrements STKLVL. 

At this point, POP examines the carry bit status. If the carry 
is clear (pass), POP goes to NEXT. If the carry is set (fail), POP 
goes to FAIL. 

NEXT and the Processes It Calls 

After initialization is finished and after each Syntax Table 
instruction is processed, NEXT is entered to process the next 
syntax instruction. 

NEXT starts by calling NXSC to increment CPC and get the 
next syntax instruction into the A register. The instruction 
value is then tested to determine which syntax instruction code 
it is and where to go to process it. 

If the Syntax Instruction is OR ($02) or RTN ($03), then exit 
is via POP. When POP is called due to these two instructions, 
the carry bit is always clear, indicating pass. 

ERNTV. If the instruction is RNTV ("GOSUB " $80 - $FF), 
then ERNTV ($A201) is entered. This code calculates the new 
CPC value, then exits via PUSH. 

GETADR. If the instruction is ANTV ($00) or the deus ex 
machina ESRT ($01) instruction, then GETADR is called. 
GETADR obtains the following two-byte address from the 
Syntax Table. 

If the instruction was ANTV, then GETADR exits via 
PUSH. 

If the instruction was ESRT, then GETADR calls the 
external routine indicated. The external routine will report 
pass/fail via the carry bit. The pass/fail condition is examined at 
$A1F0. If pass is indicated, then NEXT is entered. If fail is 
indicated, then FAIL is entered. 

TERMTST. If the instruction is VEXP ($0E), then the code at 
$A1F9 will go to TERMTST ($A2A9), which will cause the code 



44 



Chapter Five 



at $A2AF to be executed for VEXP. This code obtains the 
address, minus 1, of the ABML for the < expression > in the 
Syntax Table and exits via PUSH. 

ECHNG. If the instruction was CHNG ($0F), then ECHNG 
($A2BA) is entered via tests at $A1F9 and $A2AB. ECHNG will 
increment CPC and obtain the change-to token which will then 
replace the last previously generated token in OUTBUFF. 
ECHNG exits via RTS, which will take control back to NEXT. 

SRCONT. The Operator Token Instructions ($10-$7F) are 
handled by the SRCONT routine. SRCONT is called via tests at 
$A1F9 and $A2AD. SRCONT will examine the current source 
symbol to see if it matches the symbol represented by the 
operator token. When SRCONT has made its determination, it 
will return to the code at $A1FC. This code will examine the 
pass/fail (carry clear/set) indicator returned by SRCONT and 
take the appropriate action. (The SRCONT routine is detailed 
on the next page.) 

FAIL 

If any routine returns a fail indicator, the FAIL code at $A26C 
will be entered. FAIL will sequentially examine the 
instructions, starting at the Syntax Table address pointed to by 
CPC, looking for an OR instruction. 

If an OR instruction is found, the code at $A27D will be 
entered. This code first determines if the current statement 
symbol is the rightmost source symbol to be examined thus far. 
If it is, it will update MAXCIX. The editor will use MAXCIX to 
set the inverse video flag if the statement is erroneous. Second, 
the code restores CIX and COX to their before-failure values 
and goes to NEXT to try this new OR choice. 

If, while searching for an OR instruction, FAIL finds a RTN 
instruction, it will call POP with the carry set. Since the carry is 
set, POP will re-enter FAIL once it has restored things to the 
previous calling level. 

All instruction codes other than OR and RTN are skipped 
over by FAIL. 



45 



Chapter Five 



Pre-compiler Subroutine Descriptions 

SRCONT ($A2E6) 

The SRCONT code will be entered when an operator token 
instruction is found in the Syntax Tables by the main pre- 
compiler code. The purpose of the routine is to determine if the 
current source symbol in the user's line matches the terminal 
symbol represented by the operator token. If the symbols 
match, the token is placed into the output buffer and pass is 
returned. If the symbols do not match, fail is returned. 

SRCONT uses the value of the operator token to access the 
terminal symbol name in the Operator Name Table. The 
characters in the source symbol are compared to the characters 
in the terminal symbol. If all the characters match, pass is 
indicated. 

TNVAR, TSVAR ($A32A) 

These deus ex machina routines are called by the ESRT 
instruction. The purpose of the routines is to determine if the 
current source symbol is a valid numeric (TNVAR) or string 
(TSVAR) variable. If the source symbol is not a valid variable, 
fail is returned. 

When pass is indicated, the routine will put a variable token 
into the output buffer. The variable token ($80-$FF) is an index 
into the Variable Name Table and the Variable Value Table, 
plus $80. 

The Variable Name Table is searched. If the variable is 
already in the table, the token value for the existing variable is 
used. If the variable is not in the table, it will be inserted into 
both tables and a new token value will be used. 

A source symbol is considered a valid variable if it starts 
with an alphabetic character and it is not a symbol in the 
Operator Name Table, which includes all the reserved words. 

The variable is considered to be a string if it ends with $; 
otherwise it is a numeric variable. If it is a string variable, $ is 
stored with the variable name characters. 

The routine also determines if the variable is an array by 
looking for (. If the variable is an array, ( is stored with the 
variable name characters in the Variable Name Table. As a 
result, ABC, ABC$, and ABC(n) are all recognized as different 
variables. 



46 



Chapter Five 



TNCON ($A400) 

TNCON is called by the ESRT instruction. Its purpose is to 
examine the current source symbol for a numeric constant, 
using the floating point package. If the symbol is not a numeric 
constant, the routine returns fail. 

If the symbol is a numeric constant, the floating point 
package has converted it to a floating point number. The 
resulting six-byte constant is placed in the output buffer 
preceded by the $0E numeric constant token. The routine then 
exits with pass indicated. 

TSCON ($A428) 

TSCON is called by the ESRT instruction. Its purpose is to 
examine the current symbol for a string constant. If the symbol 
is not a string constant, the routine returns fail. 

If the first character of the symbol is ", the symbol is a 
string constant. The routine will place the string constant token 
($0F) into the output buffer, followed by a string length byte, 
followed by the string characters. 

The string constant consists of all the characters that follow 
the starting double quote up to the ending double quote. If the 
EOL character ($9B) is found before the ending double quote, 
an ending double quote is assumed. The EOL is not part of the 
string. The starting and ending double quotes are not saved 
with the string. All 256 character codes except $9B (EOL) and 
$22 (") are allowed in the string. 

SEARCH ($A462) 

This is a general purpose table search routine used to find a 

source symbol character string in a table. 

The table to be searched is assumed to have entries which 
consist of a fixed length part (0 to 255 bytes) followed by a 
variable length ATASCII part. The last character of the ATASCII 
part is assumed to have the most significant bit ($80) on. The 
last table entry is assumed to have the first ATASCII character 
as $00. 

Upon entry, the X register contains the length of the fixed 
part of the table (0 to 255). The A, Y register pair points to the 
start of the table to be searched. The source string for 
comparison is pointed to by INBUFF plus the value in CIX. 

Upon exit, the 6502 carry flag is clear if a match was found, 
and set if no match was found. The X register points to the end 



47 



Chapter Five 



of the symbol, plus 1, in the buffer. The SRCADR ($95) two- 
byte cell points to the matched table entry. STENUM ($AF) 
contains the number, relative to zero, of the matched table 
entry. 

SETCODE (A2C8) 

The SETCODE routine is used to place a token in the next 
available position in the output (token) buffer. The value in 
COX determines the current displacement into the token 
buffer. After the token is placed in the buffer, COX is 
incremented by one. If COX exceeds 255, the LINE TOO 
LONG error message is generated. 



48 



Chapter Six 



Execution Overview 



During the editing and pre-compiling phase, the user's 
statements were checked for correct syntax, tokenized, and put 
into the Statement Table. Then direct statements were passed 
to the Program Executor for immediate processing, while 
program statements awaited later processing by the Program 
Executor. 

We now enter the execution phase of Atari BASIC. The 
Program Executor consists of three parts: routines which 
simulate the function of individual statement types; an 
expression execution routine which processes expressions (for 
example, A + B + 3, A$(l,3), "HELP", A(3) + 7.26E-13); and the 
Execution Control routine, which manages the whole process. 

Execution Control 

Execution Control is invoked in two situations. If the user 
has entered a direct statement, Execution Control does some 
initial processing and then calls the appropriate statement 
execution routine to simulate the requested operation. If the 
user has entered RUN as a direct statement, the statement 
execution routine for RUN instructs Execution Control to start 
processing statements from the beginning of the statement 
table. 

When the editor has finished processing a direct statement, 
it initiates the Execution Control routine EXECNL ($A95F). 
Execution Control's job is to manage the process of statement 
simulation. 

The editor has saved the address of the statement it 
processed in STMCUR and has put the statement in the 
Statement Table. Since this is a direct statement, the line 
number is $8000, and the statement is saved as the last line in 
the Statement Table. 

The fact that a direct statement is always the last statement 
in the Statement Table gives a test for the end of a user's 
program. 

The high- order byte of the direct statement line number 
($8000) has its most significant bit on. Loading this byte ($80) 



49 



Chapter Six 



into the 6502 accumulator will set the minus flag on. The line 
number of any program statement is less than or equal to 
$7FFF. Loading the high order byte ($7F or less) of a program 
line number into the accumulator will set the 6502 minus flag 
off. This gives a simple test for a direct statement. 

Initialization 

Execution Control uses several parameters to help it manage 
the task of statement execution. 

STMCUR holds the address in the Statement Table of the 
line currently being processed. 

LLNGTH holds the length of the current line. 

NXTSTD holds the displacement in the current line of the 
next statement to process. 

STMCUR already contains the correct value when 
Execution Control begins processing. SETLN1 ($B81B) is called 
to store the correct values into LLNGTH and NXTSTD. 

Statement Execution 

Since the user may have changed his or her mind about 
execution, the routine checks to see if the user hit the break 
key. If the user did hit BREAK, Execution Control carries out 
XSTOP ($B793), the same routine that is executed when the 
STOP statement is encountered. At the end of its execution, 
the XSTOP routine gives control to the beginning of the editor. 

If the user did not hit BREAK, Execution Control checks to 
see whether we are at the end of the tokenized line. Since this 
is the first statement in the line, we can't be at the end of the 
line. So why do the test? Because this part of the routine is 
executed once for each statement in the line in order to tell us 
when we do reach the end of the line. (The end-of-line 
procedure will be discussed later in this chapter.) 

The statement length byte (the displacement to the next 
statement in the line) is the first byte in a statement. (See 
Chapter 3.) The displacement to this byte was saved in 
NXTSTD. Execution Control now loads this new statement's 
displacement using the value in NXTSTD. 

The byte after the statement length in the line is the 
statement name token. Execution Control loads the statement 
name token into the A register. It saves the displacement to the 
next byte, the first of the statement's tokens, in STINDEX for 
the use of the statement simulation routines. 



50 



Chapter Six 



The statement name token is used as an index to find this 
statement's entry in the Statement Execution Table. Each table 
entry consists of the address, minus 1, of the routine that will 
simulate that statement. This simulation routine is called by 
pushing the address from the table onto the 6502 CPU stack 
and doing an RTS. Later, when a simulation routine is 
finished, it can do an RTS and return to Execution Control. 
(The name of most of the statement simulation routines in the 
BASIC listing is the statement name preceded by an X: XFOR, 
XRUN, XLIST.) 

Most of the statement simulation routines return to 
Execution Control after processing. 

Execution Control again tests for BREAK and checks for the 
end of the line. As long as we are not at end-of-line, it 
continues to execute statements. When we reach end-of-line, it 
does some end-of-line processing. 

End-of-line Handling in a Direct Statement 

When we come to the end of the line in a direct statement, 
Execution Control has done its job and jumps to SNX3. The 
READY message is printed and control goes back to the 
Program Editor. 

End-of-line Handling during Program Execution 

Program execution is initiated when the user types RUN. 
Execution Control handles RUN like any other direct 
statement. The statement simulation routine for RUN initial- 
izes STMCUR, NXTSTD, and LLNGTH to indicate the first 
statement of the first line in the Statement Table, then returns 
to Execution Control. Execution Control treats this first 
program statement as the next statement to be executed, 
picking up the statement name tokens and calling the 
simulation routines. 

Usually, Execution Control is unaware of whether it is 
processing a direct statement or a program statement. End-of- 
line is the only time the routine needs to make a distinction. 

At the end of every program line, Execution Control gets 
the length of the current line and calls GNXTL to update the 
address in STMCUR to make the next line in the Statement 
Table the new current line. Then it calls TENDST ($A9E2) to 
test the new line number to see if it is another program line or a 
direct statement. If it is a direct statement, we are at the end of 
the user's program. 

51 



Chapter Six 



Since the direct statement includes the RUN command that 
started program execution, Execution Control does not execute 
the line. Instead, Execution Control calls the same routine that 
would have been called if the program had contained an END 
statement (XEND, at $B78D). XEND does some end-of- 
program processing, causes READY to be printed, and returns 
to the beginning of the editor. 

If we are not at the end of the user's program, processing 
continues with the new current line. 

Execution Control Subroutines 

TENDST ($A9E2) 

Exit parameters: The minus flag is set on if we are at the end of 
program. 

This routine checks for the end of the user's program in the 
Statement Table. 

The very last entry in the Statement Table is always a direct 
statement. Whenever the statement indicated by STMCUR is 
the direct statement, we have finished processing the user's 
program. 

The line number of a direct statement is $8000. The line 
number of any other statement is $7FFF or less. TENDST 
determines if the current statement is the direct statement by 
loading the high-order byte of the line number into the A 
register. This byte is at a displacement of one from the address 
in STMCUR. If this byte is $80 (a direct statement), loading it 
turns the 6502 minus flag on. Otherwise, the minus flag is 
turned off. 

GETSTMT ($A9A2) 

Entry parameters: TSLNUM contains the line number of the 
statement whose address is required. 

Exit parameters: If the line number is found, the STMCUR 
contains the address of the statement and the carry flag is set 
off (clear). If the line number does not exist, STMCUR contains 
the address where a statement with that line number should 
be, and the carry flag is set on (set). 

The purpose of this routine is to find the address of the 
statement whose line number is contained in TSLNUM. 

The routine saves the address currently in STMCUR into 
SAVCUR and then sets STMCUR to indicate the top of the 



52 



Chapter Six 



Statement Table. The line whose address is in STMCUR is 
called the current line or statement. 

GETSTMT then searches the Statement Table for the 
statement whose line number is in TSLNUM. The line number 
in TSLNUM is compared to the line number of the current line. 
If they are equal, then the required statement has been found. 
Its address is in STMCUR, so GETSTMT clears the 6502 carry 
flag and is finished. 

If TSLNUM is smaller than the current statement line 
number, GETSTMT gets the length of the current statement by 
executing GETLL ($A9DD). GNXTL ($A9D0) is executed to 
make the next line in the statement table the current statement 
by putting its address into STMCUR. GETSTMT then repeats 
the comparison of TSLNUM and the line number of the current 
line in the same manner. 

If TSLNUM is greater than the current line number, then a 
line with this line number does not exist. STMCUR already 
points to where the line should be, the 6502 carry flag is already 
set, and the routine is done. 

GETLL ($A9DD) 

Entry parameters: STMCUR indicates the line whose length is 
desired. 

Exit parameters: Register A contains the length of the 
current line. 

GETLL gets the length of the current line (that is, the line 
whose address is in STMCUR). 

The line length is at a displacement of two into the line. 
GETLL loads the length into the A register and is done. 

GNXTL ($A9D0) 

Entry parameters: STMCUR contains the address of the current 
line, and register A contains the length of the current line. 

Exit parameters: STMCUR contains the address of the next 
line. 

This routine gets the next line in the statement table and 
makes it the current line. 

GNXTL adds the length of the current line (contained in 
the A register) to the address of the current line in STMCUR. 
This process yields the address of the next line in the statement 
table, which replaces the value in STMCUR. 



53 



Chapter Six 



SETLN1 ($B81B) 

Entry parameters: STMCUR contains the address of the current 
line. 

Exit parameters: LLNGTH contains the length of the 
current line. NXTSTD contains the displacement in the line to 
the next statement to be executed (in this case, the first 
statement in the line). 

This routine initializes several line parameters so that 
Execution Control can process the line. 

The routine gets the length of the line, which is at a 
displacement of two from the start of the line. 

SETLN1 loads a value of three into the Y register to indicate 
the displacement into the line of the first statement and stores 
the value into NXTSTD as the displacement to the next 
statement for execution. 

SETLINE ($B818) 

Entry parameters: TSLNUM contains the line number of a 
statement. 

Exit parameters: STMCUR contains the address of the 
statement whose line number is in TSLNUM. LLNGTH 
contains the length of the line. NXTSTD contains the 
displacement in the line to the next statement to be executed (in 
this case, the first statement in the line). Carry is set if the line 
number does not exist. 

This routine initializes several line parameters so that 
execution control can process the line. 

SETLINE first calls GETSTMT ($A9A2) to find the address 
of the line whose number is in TSLNUM and put that address 
into STMCUR. It then continues exactly like SETLN1. 



54 



Chapter Seven 



Execute Expression 



The Execute Expression routine is entered when the Program 
Executor needs to evaluate a BASIC expression within a 
statement. It is also the executor for the LET and implied LET 
statements. 

Expression operators have an order of precedence; some 
must be simulated before others. To properly evaluate an 
expression, Execute Expression rearranges it during the 
evaluation. 

Expression Rearrangement Concepts 

Operator precedence rules in algebraic expressions are so 
simple and so unconscious that most people aren't aware of 
following them. When you evaluate a simple expression like 
Y = AX 2 + BX + C, you don't think: "Exponentiation has a 
higher precedence than multiplication, which has a higher 
precedence than addition; therefore, I will first square the X, 
then perform the multiplication." You just do it. 

Computers don't develop habits or common sense — they 
have to be specifically commanded. It would be nice if we could 
just type Y = AX 2 + BX + C into our machine and have the 
computer understand, but instead we must separate all our 
variables with operators. We also have to learn a few new 
operators, such as * for multiply and A for 
exponentiation. 

Given that we are willing to adjust our thinking this much, 
we enter Y = A*X A 2 + B*X + C . The new form of expression 
does not quite have the same feel as Y = AX 2 + BX + C; we have 
translated normal human patterns halfway into a form the 
computer can use. 

Even the operation X A 2 causes another problem for the 
computer. It would really prefer that we give it the two values 
first, then tell it what to do with them. Since the computer still 
needs separators between items, we should write X A 2 as 
X,2,A. 

Now we have something the computer can work with. It 
can obtain the two values X,2, apply the operator A , and get a 
result without having to look ahead. 

55 



Chapter Seven 



If we were to transcribe X A 2*A in the same manner, we 
would have X, 2, A , A, * . The value returned by X, 2, A is the first 
value to multiply, so the value pair for multiplication is (X,2/\) 
and A. Again we have two values followed by an operator, and 
the computer can understand. 

If we continue to transcribe the expression by pairing 
values and operators, we find that we don't want to add the 
value X A 2*A to B; we want to add the value X A 2* A to B*X. 
Therefore, we need to tell the computer X,2, A ,A,*,B,X,*, + . 
The value pair for the operator + is (X,2, A ,A,*) and (B,X,*). 

The value pair for the final operation, =, is (X,2, A ,A,*,B,X, 
*, + , C, + ) and Y. So the complete translation of Y = AX 2 + BX + 
C is X,2, A ,A,*,B,X,*, + ,C, + ,Y, = . 

Very few people other than Forth programmers put up 
with this form of expression transcription. Therefore, Atari 
BASIC was designed to perform this translation for us, 
provided we use the correct symbols, like * and A . 

The Expression Rearrangement Algorithm 

The algorithm for expression rearrangement requires two LIFO 
stacks for temporary storage of the rearranged terms. The 
Operator Stack is used for temporarily saving operators; the 
Argument Stack is used for saving arguments. Arguments are 
values consisting of variables, constants, and the constant-like 
values resulting from previous expression operations. 

Operator Precedence Table 

The Atari BASIC User's Manual lists the operators by 
precedence. The highest-precedence operators, like <, >, and 
= < , are at the top of the list; the lowest-precedence operator, 
OR, is at the bottom. The operators at the top of the list get 
executed before the operators at the bottom of the list. 

The operators in the precedence table are arranged in the 
same order as the Operator Name Table. Thus the token values 
can be used as direct indices to obtain an operator precedence 
value. 

The entry for each operator in the Operator Precedence 
Table contains two precedence values, the go-on to-stack 
precedence and the come-off-stack precedence. When a new 
operator has been plucked from an expression, its go-onto- 
stack precedence is tested in relation to the top-of-stack 
operator's come-off-stack precedence. 

56 



Chapter Seven 



Expression Rearrangement Procedure 

The symbols of the expression (the arguments and the 
operators) are accessed sequentially from left to right, then 
rearranged into their correct order of precedence by the 
following procedure: 

1. Initialize the Operator Stack with the Start Of Expression 
(SOE) operator. 

2. Get the next symbol from the expression. 

3. If the symbol is an argument (variable or constant), 
place the argument on the top of the Argument Stack. 
Go to step 2. 

4. If the symbol is an operator, save the operator in the 
temporary save cell, SAVEOP. 

5. Compare the go-onto-stack precedence of the operator 
in SAVEOP to the come-off stack precedence of the 
operator on the top of the Operator Stack. 

6. If the top-of-stack operator's precedence is less than the 
precedence of the SAVEOP operator, then the SAVEOP 
operator is pushed onto the Operator Stack. When the 
push is done, go back to step 2. 

7. If the top-of-stack operator's precedence is equal to or 
greater than the precedence of the SAVEOP operator, 
then pop the top-of-stack operator and execute it. When 
the execution is done, go back to step 5 and continue. 

The Expression Rearrangement Procedure has one 
apparent problem. It seems that there is no way to stop it. 
There are no exits for the "evaluation done" condition. This 
problem is handled by enclosing the expression with two 
special operators: the Start Of Expression (SOE) operator, and 
the End Of Expression (EOE) operator. Remember that SOE 
was the first operator placed on the Operator Stack, in step 1. 
Execution code for the SOE operator will cause the procedure 
to be exited in step 7, when SOE is popped and executed. The 
EOE operator is never executed. EOE's function is to force the 
execution of SOE. 

The precedence values of SOE and EOE are set to insure 
that SOE is executed only when the expression evaluation is 
finished. The SOE come-off-stack precedence is set so that its 
value is always less than all the other operators' go-onto-stack 
precedence values. The EOE go-onto-stack precedence is set so 
that its value is always equal to or less than all the other 



57 



Chapter Seven 



operators' (including SOE's) come-off-stack precedence 
values. 

Because SOE and EOE precedence are set this way, no 
operator other than EOE can cause SOE to be popped and 
executed. Second, EOE will cause all stacked operators, 
including SOE, to be popped and executed. Since SOE is 
always at the start of the expression and EOE is always at the 
end of the expression, SOE will not be executed until the 
expression is fully evaluated. 

In actual practice, the SOE operator is not physically part of 
the expression in the Statement Table. The Expression 
Rearrangement Procedure initializes the Operator Stack with 
the SOE operator before it begins to examine the expression. 

There is no single operator defined as the End Of 
Expression (EOE) operator. Every BASIC expression is 
followed by a symbol like :, THEN, or the EOL character. All of 
these symbols function as operators with precedence 
equivalent to the precedence of our phantom EOE operator. 
The THEN token, for example, serves a dual purpose. It not 
only indicates the THEN action, but also acts as the EOE 
operator when it follows an expression. 

Expression Rearrangement Example 

To illustrate how the expression evaluation procedure works, 
including expression rearrangement, we will evaluate our 
Y = A*X A 2 + B*X + C example and see how the expression is 
rearranged to X,2, A ,A,*,B,X,*, + ,C, +,Y, = with a correct 
result. To work our example, we need to establish a precedence 
table for the operators. The values in Figure 7-1 are similar to 
the actual values of these operators in Atari BASIC. The lowest 
precedence value is zero; the highest precedence value is $0F. 

Figure 7-1. Example Precedence Table 



operator 


go-on-stack 


come-off-stac 


symbol 


precedence 


precedence 


SOE 


NA 


$00 


+ 


$09 


$09 


* 


$0A 


$0A 


A 


$0C 


$0C 


= 


$0F 


$01 


! (EOE) 


$00 


NA 



58 



Chapter Seven 



Symbol values and notations. In the example steps, the 
term PSn refers to step n in the Expression Rearrangement 
Procedure (page 57). Step 5, for instance, will be called PS5. 

In the actual expression, the current symbol will be 
underlined. If B is the current symbol, then the actual 
expression will appear as Y = A*X 2 + B*X + C . In the 
rearranged expression, the symbols which have been evaluated 
up to that point will also be underlined. 

The values of the variables are: 

A = 2 C=6 

B=4 X=3 

The variable values are assumed to be accessed when the 
variable arguments are popped for operator execution. 
The end-of-expression operator is represented by ! . 

Example step 1. 

Actual Expression: Y = A*XA2 + B*X + C! 

Rearranged Expression: X,2, A , A, *,B,X, *, + ,C, + , Y, = , ! 

Argument Stack: 

Operator Stack: SOE 

SAVEOP: 

PS1 has been executed. The Operator Stack has been 
initialized with the SOE operator. We are ready to start 
processing the expression symbols. 

Example step 2. 

Actual Expression: Y = A*XA2 + B*X + C! 

Rearranged Expression: X,2,A ,A,*,B,X,*, + ,C, + ,Y, =,! 

Argument Stack: Y 

Operator Stack: SOE 

SAVEOP: 

The first symbol, Y, has been obtained and stacked in the 
Argument Stack according to PS2 and PS3. 

Example step 3. 

Actual Expression: Y_=A*XA 2 + B*X + C! 

Rearranged Expression: X,2,A ,A,*,B,X,*, + ,C, +,Y, =,! 

Argument Stack: Y 

Operator Stack: SOE, = 

SAVEOP: = 



59 



Chapter Seven 



Operator = has been obtained via PS2. The relative 
precedences of SOE ($00) and = ($0F) dictate that the = be 
placed on the Operator Stack via PS6. 

Example step 4. 

Actual Expression: Y=A*XA2 + B*X + C! 

Rearranged Expression: X,2, A ,A,*,B,X,*, +,C, + ,Y, =,! 

Argument Stack: Y,A 

Operator Stack: SOE, = 

SAVEOP: 

The next symbol is A. This symbol is pushed onto the 
Argument Stack via PS3. 

Example step 5. 

Actual Expression: Y = A*XA 2 + B*X + C! 

Rearranged Expression: X,2, A ,A,*,B,X,*, + ,C, + ,Y, = ,! 

Argument Stack: Y,A 

Operator Stack: SOE, = , * 

SAVEOP: * 

The next symbol is the operator *. The relative precedence 
of * and = dictates that * be pushed onto the Operator Stack. 

Example step 6. 

Actual Expression: Y = A*XA2 + B*X + C! 

Rearranged Expression: X,2,A ,A,*,B,X,*, + ,C, + ,Y, =,! 

Argument Stack: Y,A,X 

Operator Stack: SOE, = ,* 

SAVEOP: 

The next symbol is the variable X. This symbol is stacked 
on the Argument Stack according to PS3. 

Example step 7. 

Actual Expression: Y = A*XA 2 + B*X + C! 

Rearranged Expression: X,2, A ,A,*,B,X,*, +,C, + ,Y, = ,! 

Argument Stack: Y,A,X 

Operator Stack: SOE,=,*,A 

SAVEOP: A 

The next symbol is A . The relative precedence of the 
and the * dictate that A be stacked via PS6. 



60 



Chapter Seven 



Example step 8. 

Actual Expression: Y = A*XA 2_+B*X + C! 

Rearranged Expression: X,2, a , A, *,B,X, *, + ,C, + , Y, = , ! 

Argument Stack : Y, A, X, 2 

Operator Stack: SOE, = ,*,a 

SAVEOP: 

The next symbol is 2. This symbol is stacked on the 
Argument Stack via PS3. 

Example step 9. 

Actual Expression: Y = A*XA 2 + B*X + C! 

Rearranged Expression: X,2,A, A, *,B,X, *, + ,C, + , Y, = , ! 

Argument Stack: Y,A,9 

Operator Stack : SOE, = , * 

SAVEOP: + 

The next symbol is the operator + . The precedence of the 
operator that was at the top of the stack, a t [ s greater than the 
precedence of + . PS7 dictates that the top-of-stack operator be 
popped and executed. 

The a operator is popped. Its execution causes arguments 
X and 2 to be popped from the Argument Stack, replacing the 
variable with the value that it represents and operating on the 
two values yielded: X A 2 = 3 a 2 = 9. The resulting value, 9, is 
pushed onto the Argument Stack. The + operator remains in 
SAVEOP. We continue at PS5. 

Note that in the rearranged expression the first symbols, 
X,2, A , have been evaluated according to plan. 

Example step 10. 

Actual Expression: Y = A*XA 2 + B*X + C! 

Rearranged Expression: X,2,A,A,*, B,X,*, +,C, + ,Y, = ,! 

Argument Stack: Y,18 

Operator Stack: SOE, = 

SAVEOP: + 

This step originates at PS5. The SAVEOP operator, +, has 
a precedence that is less than the operator which was at the top 
of the stack, *. Therefore, according to PS7, the * is popped 
and executed. 

The execution of * results in A*9 = 2*9 = 18. The resulting 
value is pushed onto the Argument Stack. 



61 



Chapter Seven 



Example step 11. 

Actual Expression: Y = A*XA2 + B*X + C! 

Rearranged Expression: X,2,A,A,*,B,X,*, + ,C, + ,Y, = ,! 

Argument Stack: Y,18 

Operator Stack: SOE, = ,+ 

SAVEOP: 

When step 10 finished, we went to PS5. The operator in 
SAVEOP was + . Since + has a higher precedence than the top- 
of-stack operator, =, the + operator was pushed onto the 
Operator Stack via PS6. 

Example step 12. 

Actual Expression: Y = A*XA2 + B*X + C! 

Rearranged Expression: X,2,A,A,*,B,X,*, +,C, +,Y, = ,! 

Argument Stack: Y,18,B 

Operator Stack: SOE, = , + 

SAVEOP: 

The next symbol is the variable B, which is pushed onto the 
Argument Stack via PS3. 

Example step 13. 

Actual Expression: Y = A*XA 2 + B*X + C! 

Rearranged Expression: X,2,A,A,*, B,X,*, +,C, +,Y, = ,! 

Argument Stack: Y,18,B 

Operator Stack: SOE, = , + ,* 

SAVEOP: * 

The next symbol is the operator *. Since * has a higher 
precedence than the top-of-stack +, * is pushed onto the stack 
viaPS6. 

Example step 14. 

Actual Expression: Y = A*X a 2 + B*X + C! 

Rearranged Expression: X,2,A,A,*,B ,X,*, +,C, +,Y, = ,! 

Argument Stack: Y,18,B,X 

Operator Stack: SOE, = , + ,* 

SAVEOP: 

The variable X is pushed onto the Argument Stack via PS3. 

Example step 15. 

Actual Expression: Y = A*XA 2 + B*X+C! 

Rearranged Expression: X,2,A,A,*,B,X,*, + ,C, +,Y, = ,! 



62 



Chapter Seven 



Argument Stack: Y,18,12 
Operator Stack: SOE, =,+ 
SAVEOP: + 

The operator + is retrieved from the expression. Since + 
has a lower precedence than * which is at the top of the stack, 
* is popped and executed. 

The execution of * causes B*X = 4*3 = 12. The resulting 
value of 12 is pushed onto the Argument Stack. We will 
continue at PS5 via the PS7 exit rule. 

Example step 16. 

Actual Expression: Y = A*XA 2 + B*X + C! 

Rearranged Expression: X,2,A,A,*,B,X,*, + , C, + ,Y, = ,! 

Argument Stack: Y,30 

Operator Stack: SOE, = 

SAVEOP: + 

This step starts at PS5. The SAVEOP operator, +, has 
precedence that is equal to the precedence of the top-of-stack 
operator, also + . Therefore, + is popped from the operator 
stack and executed. The results of the execution cause 18 + 12, 
or 30, to be pushed onto the Argument Stack. PS5 is called. 

Example step 17. 

Actual Expression: Y = A*XA2 + B*X + C! 

Rearranged Expression: X,2,A,A,*,B,X,*, + , C, +,Y, =,! 

Argument Stack: Y,30 

Operator Stack: SOE, = , + 

SAVEOP: 

This step starts at PS5. The SAVEOP is + . The top-of-stack 
operator, =, has a lower precedence than +; therefore, + is 
pushed onto the stack via PS6. 

Example step 18. 

Actual Expression: Y = A*XA 2 + B*X + C! 

Rearranged Expression: X,2,A,A,*,B,X,*, + , C, + ,Y, = ,! 

Argument Stack: Y,30,C 

Operator Stack: SOE, = , + 

SAVEOP: 

The variable C is pushed onto the Argument Stack via PS3. 



63 



Chapter Seven 



Example step 19. 

Actual Expression: Y=A*XA2+B*X + C! 

Rearranged Expression: X,2, A ,A,*,B,X,*, + ,C, + , Y, = , ! 

Argument Stack: Y,36 

Operator Stack: SOE, = 

SAVEOP: ! 

The EOE operator ! is plucked from the expression. The 
EOE has a lower precedence than the top-of-stack + operator. 
Therefore, + is popped and executed. The resulting value of 
30 + 6, 36, is pushed onto the Argument Stack. PS5 will execute 
next. 

Example step 20. 

Actual Expression: Y=A*XA 2+B*X + C[ 

Rearranged Expression: X,2, A /A,*,B,X,*, + ,C, + ,Y, =, ! 

Argument Stack: 

Operator Stack: SOE 

SAVEOP: ! 

This step starts at PS5. The ! operator has a lower 
precedence than the top-of-stack = operator, which is popped 
and executed. The execution of = causes the value 36 to be 
assigned to Y. This leaves the Argument Stack empty. PS5 will 
be executed next. 

Example step 21. 

Actual Expression: Y = A*XA 2 + B*X + C| 

Rearranged Expression: X,2,A,A,*,B,X,*, + ,C, + ,Y, = ,! 

Argument Stack: 

Operator Stack: 

SAVEOP: ! 

The ! operator in SAVEOP causes the SOE operator to be 
popped and executed. The execution of SOE terminates the 
expression evaluation. 

Note that the rearranged expression was executed exactly 
as predicted. 

Mainline Code 

The Execute Expression code implements the Expression 
Rearrangement Procedure. The mainline code starts at the 
EXEXPR label at $AAE0. The input to EXEXPR starts at the 
current token in the current statement. STMCUR points to the 

64 



Chapter Seven 



current statement. STINDEX contains the displacement to the 
current token in the STMCUR statement. The output of 
EXEXPR is whatever values remain on the top of the argument 
stack when the expression evaluation is finished. 

In the following discussion, PSn refers to the procedure 
step n in the Expression Rearrangement Procedure. 

PS1, initialization, occurs when EXEXPR is entered. 
EXPINT is called to initialize the operator and argument stacks. 
EXPINT places the SOE operator on the operator stack. 

PS2, which obtains the next token, directly follows 
initialization at EXNXT ($AAE3). The code calls EGTOKEN to 
get the next expression symbol and classify it. If the token is an 
argument, the carry will be set. If the token is an operator, the 
carry will be clear. 

If the token is an argument, PS3 is implemented via a call to 
ARGPUSH. After the argument is pushed onto the argument 
stack, EXNXT (PS2) will receive control. 

If the token was an operator, then the code at EXOT 
($AAEE) will be executed. This code implements PS4 by saving 
the token in EXSVOP. 

PS5, which compares the precedents of the EXSVOP token 
and the top-of-stack token, follows EXOT at EXPTST ($AAFA). 
This code also executes the SOE operator. If SOE is popped, 
then Execute Expression finishes via RTS. 

If the top-of-stack operator precedence is less than the 
EXSVOP operator precedence, PS6 is implemented at 
EOPUSH ($AB15). EOPUSH pushes EXSVOP onto the 
operator stack and then goes to EXNXT (PS2). 

If the top-of-stack operator precedence is greater than or 
equal to the EXSVOP operator precedence, then PS7 is 
implemented at EXOPOP ($AB0B). EXOPOP will pop the top- 
of-stack operator and execute it by calling EXOP. When EXOP 
is done, control passes to EXPTST (PS5). 

Expression Evaluation Stacks 

The two expression evaluation stacks, the Argument Stack and 
the Operator Stack, share a single 256-byte memory area. The 
Argument Stack grows upward from the lower end of the 256- 
byte area. The Operator Stack grows downward front the 
upper end of the 256-byte area. 

The 256-byte stack area is the multipurpose buffer at the 
start of the RAM tables. The buffer is pointed to by the 

65 



Chapter Seven 



ARGSTK (also ARGOPS) zero-page pointer at $80. The current 
index into the Argument Stack is maintained by ARSLVL 
($AA). When the Argument Stack is empty, ARSLVL is zero. 

The OPSTKX cell maintains the current index into the 
Operator Stack. When the Operator Stack is initialized with the 
SOE operator, OPSTKX is initialized to $FF. As operators are 
added to the Operator Stack, OPSTKX is decremented. As 
arguments are added to the Argument Stack, ARSLVL is 
incremented. 

Since the two stacks share a single 256-byte memory area, 
there is a possibility that the stacks will run into each other. The 
code at $ABC1 is used to detect a stack collision. It does this by 
comparing the values in ARSLVL and OPSTKX. If ARSLVL is 
greater than or equal to OPSTKX, then a stack collision occurs, 
sending the STACK OVERFLOW error to the user. 

Operator Stack 

Each entry on the Operator Stack is a single-byte operator-type 
token. Operators are pushed onto the stack at EXOPUSH 
($AB15) and are popped from the stack at EXOPOP ($AB0B). 

Argument Stack 

Each entry on the Argument Stack is eight bytes long. The 
format of these entries is described in Figures 7-2, 7-3, and 7-4, 
and are the same as the formats for entries in the Variable Value 
Table. 

Unlike the Variable Value Table, the Argument Stack must 
deal with both variables and constants. In Figure 7-2, we see 
that VNUM is used to distinguish variable entries from 
constant entries. 

The SADR and AADR fields in the entries for strings and 
arrays are of special interest. (See Figures 7-3 and 7-4.) When a 
string or array variable is dimensioned, space for the variable is 
created in the string/array space. The displacement to the start 
of the variable's area within the string/array space is placed in 
the SADR/ AADR fields at that time. A displacement is used 
rather than an absolute address because the absolute address 
can change if any program changes are made after the DIM 
statement is executed. 

Execute Expression needs these values to be absolute 
address values within the 6502 address space. When a 
string/array variable is retrieved from the Variable Value Table, 



66 



Chapter Seven 



the displacement is transformed to an absolute address. When 
(and if) the variable is put back into the Variable Value Table, 
the absolute address is converted back to a displacement. 

The entries for string constants also deserve some special 
attention. String constants are the quoted strings within the 
user program. These strings become part of the tokenized 
statements in the Statement Table. When Execute Expression 
gets a string token, it will create a string constant Argument 
Stack entry. This entry's SADR is an absolute address pointer 
to the string in the Statement Table. SLEN and SDIM are set to 
the actual length of the quoted string. 

Argument Work Area 

An argument which is currently being examined by Execute 
Expression is kept in a special zero-page Argument Work Area 
(AWA). The AW A starts at the label VTYPE at $D2. 



Figure 7-2. Argument Stack Entry 

1 2 



VTYPE 



VNUM 



DATA 



■*• Data Field. Format depends on VTYPE. 

If VNUM = 0, the entry is a constant. 
If VNUM > 0, the entry is a variable. In this case, 
the VNUM value is the entry number in the Variable 
Value Table. The token representing this variable is 
VNUM + $80. 

- $00 = Data is a six-byte floating point constant. 
$80 = Data represents an undimensioned string. 
$81 = Data represents a dimensioned string with 

a relative address pointer. 
$83 = Data represents a dimensioned string with 

an absolute address pointer. 
$40 = Data represents an undimensioned array. 
$41 = Data represents a dimensioned array with 

a relative address pointer. 
u $43 = Data represents a dimensioned array with 

an absolute address pointer. 



67 



Chapter Seven 



Figure 7-3. Argument Stack String Entry 



VTYPE 



VNUM 



SADR 



SLEN 



SDIM 



J 



\_^jr Dimensioned length of the string. Valid only if 
L VTYPE = $81 or $83. 

i-Current length of the string. Valid only if VTYPE 
*T- =<R81 or <R83 



= $81 or $83. 

p String address. Valid only if VTYPE = $81 or $83. 
If VTYPE = $81, then SADR is the displacement 
of the start of the string from the start of the 
string/array space. 

If VTYPE = $83, then SADR is the absolute address 
L of the start of the string. 



Figure 7-4. Argument Stack Array Entry 



VTYPE VNUM AADR 



DIM1 



DIM2 



J 



- When an array has been dimensioned as A(D1,D2), 
this field contains the D2 value. If an array 
was dimensioned as A(D1), then this field is 
zero. The field is valid only if VTYPE = $41 or 

u $43. 

■ When an array has been dimensioned, as A(D1,D2) 
or as A(D1), this field contains the Dl value. 

■ The field is valid only if VTYPE = $41 or $43. 

■ Array Address. Valid only if VTYPE = $41 or $43. 

If VTYPE = $41, the AADR is the displacement to 
the start of the array in the string/array space. 

If VTYPE = $43, the AADR is the absolute address 
L of the start of the string. 



68 



Chapter Seven 



Operator Executions 

An operator is executed when it is popped from the Operator 
Stack. Execute Expression calls EXOP at $AB20 to start this 
execution. The EXOP routine uses the operator token value as 
an index into the Operator Execution Table ($AA70). The 
operator execution address from this table, minus 1, is placed 
on the 6502 CPU stack. An RTS is then executed to begin 
executing the operator's code. 

The names of the operator execution routines all begin with 
the characters XP. 

All the Atari BASIC functions, such as PEEK, RND, and 
ABS, are executed as operators. 

Most routines for the execution of the operators are very 
simple and straightforward. For example, the * operator 
routine, XPMUL ($AC96), pops two arguments, multiplies 
them via the floating point package, pushes the result onto the 
argument stack, and returns. 

String, Array, DIM, and Function Operations 

Any array reference in an expression may be found in one of 
two forms: A(x) or A(x,y). The indices x and y may be any 
valid expression. The intent of the indices is to reference a 
specific array element. 

Before the specific element reference can take place, the x 
and/or y index expressions must be fully evaluated. To do this, 
the characters '(' ',' and ')' are made operators. The 
precedence of these operators forces things to happen in the 
correct sequence. Figure 7-5 shows the relative precedence of 
these operators for an array. 

Figure 7-5. Array Operator Precedence 

come-off-stack 
precedence 

$02 
$03 
$0E 

As a result of these precedence values, ( has a high 
enough precedence to go onto the stack, no matter what other 
operator is on the top of the stack. 

69 



operator 
symbol 


go-on-stack 
precedence 


( 

, (comma) 

) 


$0F 
$04 
$04 



Chapter Seven 



The comma's goon-stack precedence will force all operators 
except ( to be popped and executed. As a result, the x index 
sub-expression, in the expression A(.v,i/), will be fully evaluated 
and the final x index value will be pushed onto the Argument 
Stack. 

The comma will then be placed onto the Operator Stack. Its 
come-off-stack precedence is such that no other operator, 
except ) , will pop it off. 

The ) operator precedence will force any 1/ index 
expression to be fully evaluated and the y index result value to 
be placed onto the Argument Stack. 

It will then force the comma operator to be popped and 
executed. This action results in a comma counter being 
incremented. 

The ) will then force the ( to be popped and executed. 
The execution of ( results in the proper array element being 
referenced. The ( operator will pop the indices from the 
Argument Stack. The number of indices (either zero or one) to 
be popped is governed by the comma counter, which was 
incremented by one for each comma that was popped and 
executed. 

Atari BASIC has numerous ( tokens, and each causes a 
different ( routine to be executed. These ( operators are array 
(CALPRN), string (CSLPRN), array DIM (CDLPRN), string DIM 
(CDSLPR), function (CFLPRN), and the expression grouping 
CLPRN operator. The Syntax Table pseudo-instruction CHNG 
is used to change the CLPRN token to the other ( tokens in 
accordance with the context of the grammar. 

The expression operations for each of these various ( 
operators in relation to commas and ( is exactly the same. 
When ( is executed, the comma count will show how many 
arguments the operator's code must pop from the argument 
stack. Each of these arguments will have been evaluated down 
to a single value in the form of a constant. 



70 



Chapter Eight 



Execution Boundary 

Conditions 



BASIC Language statements can be divided into groups with 
related functions. The execution boundary statements, RUN, 
STOP, CONT and END, cause a BASIC program to start or 
stop executing. The routines which simulate these statements 
are XRUN, XSTOP, XCONT, and XEND. 

Program Termination Routines 

Any BASIC statement can be used as either a direct statement 
or a program statement, but some only make sense in one 
mode. The STOP statement has no real meaning when entered 
as a direct statement. When the statement simulation routine 
for STOP is asked to execute in direct mode, it does as little 
processing as possible and exits. Useful processing occurs only 
when STOP is a program statement. 

STOP ($B7A7). The XSTOP and XEND routines are similar and 
perform some of the same tasks. The tasks common to both are 
handled by the STOP routine. 

If this statement is not a direct statement, the STOP routine 
saves the line number of the current line in STOPLN. This line 
number is used later for printing the STOPed message. It is 
also used by the CONT simulation routine (XCONT) to 
determine where to restart program execution. (Since XEND 
also uses this routine, it is possible to CONTinue after an END 
statement in the middle of a program.) 

The STOP routine also resets the LIST and ENTER devices 
to the screen and the keyboard. 

XSTOP ($B793). XSTOP does the common STOP processing 
and then calls :LPRTOKEN($B535) to print the STOPed 
message. It then calls one of the error printing routines, 
:ERRM2 ($B974), to output the AT LINE nnn portion. The 
:ERRM2 routine will not print anything if this was a direct 
statement. When :ERRM2 is finished, it jumps back to the start 
of the editor. 



71 



Chapter Eight 



XEND ($B78D). XEND calls the STOP routine to save the 
current line number. It then transfers to the start of the editor 
via the SNX1 entry point. This turns off the sound, closes any 
open IOCBs, and prints the READY message. XEND also 
leaves values on the 6502 CPU stack. These values are thrown 
away when the editor resets the stack. 

END OF PROGRAM. A user may have neglected to include an 
END statement in his program. In this case, when Execution 
Control comes to the end of the Statement Table it calls XEND, 
and the program is terminated exactly as if the last statement in 
the program were an END. 

Program Initiation Routines 

The statements that cause a user's program to begin execution 
are RUN and CONT. These statements are simulated by XRUN 
and XCONT. 

XCONT ($B7BE). The CONT statement has no meaning when 
encountered as a program statement, so its execution has no 
effect. 

When the user enters CONT as a direct statement, XCONT 
uses the line number that was saved in STOPLN to set 
Execution Control's line parameters (STMCUR, NXTSTD, 
and LLNGTH). This results in the current line being the line 
following the one whose line number is in STOPLN. This 
means that any statement following STOP or END on a line 
will not be executed; therefore, STOP and END should always 
be the last statement in the line. 

If we are at the end of the Statement Table, XCONT 
terminates as if an END statement had been encountered in the 
program. If there are more lines to process, XCONT returns to 
Execution Control, which resumes processing at the line whose 
address was just put into STMCUR. 

XRUN ($B74D). The RUN statement comes in two formats, 
RUN and RUN < filespec > . In the case of RUN < filespec > , 
XRUN executes XLOAD to load a saved program, which 
replaces the current one in memory. The process then proceeds 
like RUN. 

XRUN sets up Execution Control's line pointers to indicate 
the first line in the Statement Table. It clears some flags used to 
control various other BASIC statements; for example, it resets 
STOPLN to 0. It closes all IOCBs and executes XCLR to reset all 



72 



Chapter Eight 



the variables to zero and get rid of any entries in the 
String/ Array Table or the Runtime Stack. 

If there is no program, so the only thing in the Statement 
Table is the direct statement, then XRUN does some clean-up, 
prints READY, and returns to the start of the editor, which 
resets the 6502 CPU stack. 

If there is a program, XRUN returns to Execution Control, 
which starts processing the first statement in the table as the 
current statement. 

When RUN < filespec > is used as a program statement, it 
performs the useful function of chaining to a new program, but 
if RUN alone is used as a program statement, an infinite loop 
will probably result. 

Error Handling Routine 

There are other conditions besides the execution boundary 
statements that terminate a program's execution. The most 
familiar are errors. 

There are two kinds of errors that can occur during 
execution: Input/Output errors and BASIC language errors. 

Any BASIC routine that does I/O calls the IOTEST routine 
($BCB3) to check the outcome of the operation. If an error that 
needs to be reported to the user is indicated, IOTEST gets the 
error number that was returned by the Operating System and 
joins the Error Handling Routine, ERROR ($B940), which 
finishes processing the error. 

When a BASIC language error occurs, the error number is 
generated by the Error Handling Routine. This routine 
calculates the error by having an entry point for every BASIC 
language error. At each entry point, there is a 6502 instruction 
that increments the error number. By the time the main 
routine, ERROR, is reached, the error number has been 
generated. 

The Error Handling Routine calls STOP ($B7A7) to save the 
line number of the line causing the error in STOPLN. It tests 
TRAPLN to see if errors are being TRAPed. The TRAP option is 
on if TRAPLN contains a valid line number. In this case, the 
Error Handler does some clean-up and joins XGOTO, which 
transfers processing to the desired line. 

If the high-order byte of the line number is $80 (not a valid 
line number), then we are not TRAPing errors. In this case, the 
Error Handler prints the four-part error message, which 



73 



Chapter Eight 



consists of ERROR, the error number, AT LINE, and finally the 
line number. If the line in error was a direct statement, the AT 
LINE part is not printed. The error handler resets ERRNUM to 
zero and is finished. 

The Error Handling Routine does not do an orderly return, 
but jumps back to the start of the editor at the SYNTAX entry 
point where the 6502 stack is reset, clearing it of the now- 
unwanted return addresses. 



74 



Chapter Nine 



Program Flow 
Control Statements 



Execution Control always processes the statement in the 
Statement Table that follows the one it thinks it has just 
finished. This means that statements in a BASIC program are 
usually processed in sequential order. 

Several statements, however, can change that order: 
GOTO, IF, TRAP, FOR, NEXT, GOSUB, RETURN, POP, and 
ON. They trick Execution Control by changing the parameters 
that it maintains. 

Simple Flow Control Statements 

XGOTO ($B6A3) 

The simplest form of flow control transfer is the GOTO 
statement, simulated by the XGOTO routine. 

Following the GOTO token in the tokenized line is an 
expression representing the line number of the statement that 
the user wishes to execute next. The first thing the XGOTO 
routine does is ask Execute Expression to evaluate the 
expression and convert it to a positive integer. XGOTO then 
calls the GETSTMT routine to find this line number in the 
Statement Table and change Execution Control's line 
parameters to indicate this line. 

If the line number does not exist, XGOTO restores the line 
parameters to indicate the line containing the original GOTO, 
and transfers to the Error Handling Routine via the ERNOLN 
entry point. The Error Handling Routine processes the error 
and jumps to the start of the editor. 

If the line number was found, XGOTO jumps to the 
beginning of Execution Control (EXECNL) rather than 
returning to the point in the routine from which it was called. 
This leaves garbage on the 6502 CPU stack, so XGOTO first 
pulls the return address off the stack. 



75 



Chapter Nine 



X1F ($B778) 

The IF statement changes the statement flow based on a 
condition. The simulation routine, XIF, begins by calling a 
subroutine of Execute Expression to evaluate the condition. 
Since this is a logical (rather than an arithmetic) operation, we 
are only interested in whether the value is zero or non-zero. If 
the expression was false (non-zero), XIF modifies Execution 
Control's line parameters to indicate the end of this line and 
then returns. Execution Control moves to the next line, 
skipping any remaining statements on the original IF statement 
line. 

If the expression is true (zero), things get a little more 
complicated. Back during syntaxing, when a statement of the 
form IF < expression > THEN < statement > was encountered, 
the pre-compiler generated an end-of-statement token after 
THEN. XIF now tests for this token. If we are at the end of the 
statement, XIF returns to Execution Control, which processes 
what it thinks is the next statement in the current line, but 
which is actually the THEN < statement > part of the IF 
statement. 

If XIF does not find the end-of-statement token, then the 
statement must have had the form IF < expression > THEN 
< line number > . XIF jumps to XGOTO, which finishes 
processing by changing Execution Control's line parameters to 
indicate the new line. 

XTRAP ($B7E1) 

The TRAP statement does not actually change the program 
flow when it is executed. Instead, the XTRAP simulation 
routine calls a subroutine of Execute Expression to evaluate the 
line number and then saves the result in TRAPLN ($BC). 

The program flow is changed only if there is an error. The 
Error Handling Routine checks TRAPLN. If it contains a valid 
line number, the error routine does some initial set-up and 
joins the XGOTO routine to transfer to the new line. 

Runtime Stack Routines 

The rest of the Program Flow Control Statements use the 
Runtime Stack. They put items on the stack, inspect them, 
and/or remove them from the stack. 

Every item on the Runtime Stack contains a four-byte 
header. This header consists of a one-byte type indication, a 

76 



Chapter Nine 



two-byte line number, and a one-byte displacement to the 
Statement Name Token. (See pages 18-19.) The type byte is the 
last byte placed on the stack for each entry. This means that the 
pointer to the top of the Runtime Stack (RUNSTK) points to the 
type byte of the most recent entry on the stack. A zero type 
byte indicates a GOSUB-type entry. Any non-zero type byte 
represents a FOR-type entry. 

A GOSUB entry consists solely of the four-byte header. A 
FOR entry contains twelve additional bytes: a six-byte limit 
value and a six-byte step value. 

Several routines are used by more than one of the 
statement simulation routines. 

PSHRSTK ($B683) This routine expands the Runtime Stack 
by calling EXPLOW and then storing the type byte, line 
number, and displacement of the Statement Name Token on 
the stack. 

POPRSTK ($B841) This routine makes sure there really is 
an entry on the Runtime Stack. POPRSTK saves the 
displacement to the statement name token in SVDISP, saves 
the line number in TSLNUM, and puts the type/variable 
number in the 6502 accumulator. It then removes the entry by 
calling the CONTLOW routine. 

:GETTOK ($B737) This routine first sets up Execution 
Control's line parameters to point to the line whose number is 
in the entry just pulled from the Runtime Stack. If the line was 
found, :GETTOK updates the line parameters to indicate that 
the statement causing this entry is now the current statement. 
Finally, it loads the 6502 accumulator with the statement name 
token from the statement that created this entry and returns to 
its caller. 

If the line number does not exist, :GETTOK restores the 
current statement address and exits via the ERGFDEL entry 
point in the Error Handling Routine. 

Now let's look at the simulation routines for the statements 
that utilize the Runtime Stack. 

XFOR ($B64B) 

XFOR is the name of the simulation routine which executes a 
FOR statement. 

In the statement FOR I = 1 TO 10 STEP 2: 
/ is the loop control variable 

77 



Chapter Nine 



1 is its initial value 
10 is the limit value 

2 is the step value 

XFOR calls Execute Expression, which evaluates the initial 
value and puts it in the loop control variable's entry in the 
Variable Value Table. 

Then it calls a routine to remove any currently unwanted 
stack entries — for example, a previous FOR statement that 
used the same loop control variable as this one. 

XFOR calls a subroutine of Execute Expression to evaluate 
the limit and step values. If no step value was given, a value of 
1 is assigned. It expands the Runtime Stack using EXPLOW 
and puts the values on the stack. 

XFOR uses PSHRSTK to put the header entry on the stack. 
It uses the variable number of the loop control variable 
(machine-language ORed with $80) as the type byte. XFOR 
now returns to Execution Control, which processes the 
statement following the FOR statement. 

The FOR statement does not change program flow. It just 
sets up an entry on the Runtime Stack so that the NEXT 
statement can change the flow. 

XNEXT ($B6CF) 

The XNEXT routine decides whether to alter the program flow, 
depending on the top Runtime Stack entry. XNEXT calls the 
POPRSTK routine repeatedly to remove four-byte header 
entries from the top of the stack until an entry is found whose 
variable number (type) matches the NEXT statement's variable 
token. If the top-of-stack or GOSUB-type entry is encountered, 
XNEXT transfers control to an Error Handling Routine via the 
ERNOFOR entry point. 

To compute the new value of the loop variable, XNEXT 
calls a subroutine of Execute Expression to retrieve the loop 
control variable's current value from the Variable Value Table, 
then gets the step value from the Runtime Stack, and finally 
adds the step value to the variable value. XNEXT again calls an 
Execute Expression subroutine to update the variable's value in 
the Variable Value Table. 

XNEXT gets the limit value from the stack to determine if 
the variable's value is at or past the limit. If so, XNEXT returns 
to Execution Control without changing the program flow, and 
the next sequential statement is processed. 

78 



Chapter Nine 



If the variable's value has not reached the limit, XNEXT 
returns the entry to the Runtime Stack and changes the 
program flow. POPRSTK already saved the line number of the 
FOR statement in TSLNUM and the displacement to the 
statement name token in SVDISP. XNEXT calls the :GETTOK 
routine to indicate the FOR statement as the current statement. 

If the token at the saved displacement is not a FOR 
statement name token, then the Error Handling Routine is 
given control at the ERGFDEL entry point. Otherwise, XNEXT 
returns to Execution Control, which starts processing with the 
statement following the FOR statement. 

XGOSUB ($B6A0) 

The GOSUB statement causes an entry to be made on the 

Runtime Stack and also changes program flow. 

The XGOSUB routine puts the GOSUB-type indicator 
(zero) into the 6502 accumulator and calls PSHRSTK to put a 
four-byte header entry on the Runtime Stack for later use by 
the simulation routine for RETURN. XGOSUB then processes 
exactly like XGOTO. 

XRTN ($B719) 

The RETURN statement causes an entry to be removed from 
the Runtime Stack. The XRTN routine uses the information in 
this entry to determine what statement should be processed 
next. 

The XRTN first calls POPRSTK to remove a GOSUB-type 
entry from the Runtime Stack. If there are no GOSUB entries 
on the stack, then the Error Handling Routine is called at 
ERBRTN. Otherwise, XRTN calls :GETTOK to indicate that the 
statement which created the Runtime Stack entry is now the 
current statement. 

If the statement name token at the saved displacement is 
not the correct type, then XRTN exits via the Error Handling 
Routine's ERGFDEL entry point. Otherwise, control is 
returned to the caller. When Execution Control was the caller, 
then GOSUB must have created the stack entry, and 
processing will start at the statement following the GOSUB. 

Several other statements put a GOSUB-type entry on the 
stack when they need to mark their place in the program. They 
do not affect program flow and will be discussed in later 
chapters. 



79 



Chapter Nine 



XPOP ($B841) 

The XPOP routine uses POPRSTK to remove an entry from the 
Runtime Stack. A user might want to do this if he decided not 
to RETURN from a GOSUB. 

XON ($B7ED) 

The ON statement comes in two versions: ON-GOTO and ON- 
GOSUB. Only ON-GOSUB uses the Runtime Stack. 

The XON routine evaluates the variable and converts it to 
an integer (MOD 256). If the value is zero, XON returns to 
Execution Control without changing the program flow. 

If the value is non-zero and this is an ON-GOSUB 
statement, XON puts a GOSUB-type entry on the Runtime 
Stack for RETURN to use later. 

From this point, ON-GOSUB and ON-GOTO perform in 
exactly the same manner. XON uses the integer value 
calculated earlier to index into the tokenized statement line to 
the correct GOTO or GOSUB line number. If there is no line 
number corresponding to the index, XON returns to Execution 
Control without changing program flow. Otherwise, XON 
joins XGOTO to finish processing. 



80 



Chapter Ten 



Tokenized Program 
Save and Load 



The tokenized program can be saved to and reloaded from a 
peripheral device, such as a disk or a cassette. The primary 
statement for saving the tokenized program is SAVE. The 
saved program is reloaded into RAM with the LOAD 
statement. The CSAVE and the CLOAD statements are special 
versions of SAVE and LOAD for use with a cassette. 

Saved File Format 

The tokenized program is completely contained within the 
Variable Name Table, the Variable Value Table, and the 
Statement Table. However, since these tables vary in size, we 
must also save some information about the size of the tables. 

The SAVE file format is shown in Figure 10-1. The first part 
consists of seven fields, each of them two bytes long, which tell 
where each table starts or ends. Part two contains the saved 
program's Variable Name Table (VNT), Variable Value Table 
(WT), and Statement Table (ST). 

The displacement value in all the part-one fields is actually 
the displacement plus 256. We must subtract 256 from each 
displacement value to obtain the true displacement. 

The VNT starts at relative byte zero in the file's second 
part. The second field in part one holds that value plus 256. 

The DWT field in part one contains the displacement, 
minus 256, of the VVT from the start of part two. 

The DST value, minus 256, gives the displacement of the 
Statement Table from the start of part two. 

The DEND value, minus 256, gives the end-of-file 
displacement from the start of part two. 



81 



Chapter Ten 



Figure 10-1. SAVE File Format 



PARTI 




2 

4 

6 

8 

10 

12 
14 







256 




Not Used. 




DVVT 




DST 




Not Used. 




DEND 


PART 2 



r-256 

r-256 

)-256 


VNT 


DVV" 


VVT 


DSN' 


ST 


DENI 





The displacement of the VNT from 
the beginning of part two, plus 256. 

The displacement of VVT from the 
' beginning of part two, plus 256. 

> The displacement of the ST from the 
beginning of part two, plus 256. 

The displacement of the end of the 
file from the beginning of part two. 

i Variable Name Table 



Variable Value Table 



Statement Table 



XSAVE ($BB5D) 

The code that implements the SAVE statement starts at the 
XSAVE ($BB5D) label. Its first task is to open the specified 
output file, which it does by calling ELADVC. 

The next operation is to move the first seven RAM table 
pointers from $80 to a temporary area at $500. While these 
pointers are being moved, the value contained in the first 
pointer is subtracted from the value in each of the seven 
pointers, including the first. 

Since the first pointer held the absolute address of the first 
RAM table, this results in a list of displacements from the first 
RAM table to each of the other tables. These seven two-byte 
displacements are then written from the temporary area to the 
file via 103. These are the first fourteen bytes of the SAVE file. 
(See Figure 10-1.) 

The first RAM table is the 256-byte buffer, which will not be 
SAVEd. This is why the seven two-byte fields at the beginning 
of the SAVEd file hold values exactly 256 more than the true 



82 



Chapter Ten 



displacement of the tables they point to. (The LOAD procedure 
will resolve the 256-byte discrepancy.) 

The next operation is to write the three needed RAM 
tables. The total length of these tables is determined from the 
value in the seventh entry in the displacement list, minus 256. 
To write the three entries, we point to the start of the Variable 
Name Table and call 104, with the length of the three tables. 
This saves the second part of the file format. 

The file is then closed and XSAVE returns to Execution 
Control. 

XLOAD ($BAFB) 

The LOAD statement is implemented at the XLOAD label 
located at $BAFB. 

XLOAD first opens the specified load file for input by 
calling ELADVC. BASIC reads the first fourteen bytes from the 
file into a temporary area starting at $500. These fourteen bytes 
are the seven RAM table displacements created by SAVE. 

The first two bytes will always be zero, according to the 
SAVE file format. (See Figure 10-1.) BASIC tests these two 
bytes for zero values. If these bytes are not zero, BASIC 
assumes the file is not a valid SAVE file and exits via the 
ERRNSF, which generates error code 21 (Load File Error). 

If this is a valid SAVE file, the value in the pointer at $80 
(Low Memory Address) is added to each of the seven displace- 
ments in the temporary area. These values will be the memory 
addresses of the three RAM tables, if and when they are read 
into memory. 

The seventh pointer in the temporary area contains the 
address where the end of the Statement Table will be. If this 
address exceeds the current system high memory value, the 
routine exits via ERRPTL, which generates error code 19 (Load 
Program Too Big). 

If the program will fit, the seven addresses are moved from 
the temporary area to the RAM table pointers at $80. The 
second part of the file is then loaded into the area now pointed 
to by the Variable Name Table pointer $82. The file is closed, 
CLR is executed, and a test for RUN is made. 

If RUN called XLOAD, then a value of $FF was pushed 
onto the CPU stack. If RUN did not call XLOAD, then $00 was 
pushed onto the CPU stack. If RUN was the caller, then an RTS 
is done. 



83 



Chapter Ten 



If XLOAD was entered as a result of a LOAD or CLOAD 
statement, then XLOAD exits directly to the Program Editor, 
not to Execution Control. 

CSAVE and CLOAD 

The CSAVE and CLOAD statements are special forms of SAVE 
and LOAD. These two statements assume that the 
SAVE/LOAD device is the cassette device. 

CSAVE is not quite the same as SAVE "C:". Using SAVE 
with the "C:" device name will cause the program to be saved 
using long cassette inter-record gaps. This is a time waster, and 
CSAVE uses short inter-record gaps. 

CSAVE starts at XCSAVE ($BBAC). CLOAD starts at 
XCLOAD($BBA4). 



84 



Chapter Eleven 



The LIST and ENTER 

Statements 



LIST can be used to store a program on an external device and 
ENTER can retrieve it. The difference between LOAD-SAVE 
and LIST-ENTER is that LOAD-SAVE deals with the tokenized 
program, while LIST-ENTER deals with the program in its 
source (ATASCII) form. 

The ENTER Statement 

BASIC is in ENTER mode whenever a program is not 
RUNning. By default the Program Editor looks for lines to be 
ENTERed from the keyboard, but the editor handles all 
ENTERed lines alike, whether they come from the keyboard or 
not. 

The Enter Device 

To accomplish transparency of all input data (not just ENTERed 
lines), BASIC maintains an enter device indicator, ENTDTD 
($B4). When a BASIC routine (for example, the INPUT 
simulation routine) needs data, an I/O operation is done to the 
IOCB specified in ENTDTD. When the value in ENTDTD is 
zero, indicating IOCB 0, input will come from the keyboard. 
When data is to come from some other device, ENTDTD 
contains a number indicating the corresponding IOCB. During 
coldstart initialization, the enter device is set to IOCB 0. It is 
also reset to at various other times. 

XENTER ($BACB) 

The XENTER routine is called by Execution Control to simulate 
the ENTER statement. XENTER opens IOCB 7 for input using 
the specified < filespec > , stores a 7 in the enter device 
ENTDTD, and then jumps to the start of the editor. 

Entering from a Device 

When the Program Editor asks GLGO, the get line routine 
($BA92), for the next line, GLGO tells CIO to get a line from the 



85 



Chapter Eleven 



device specified in ENTDTD — in this case, from IOCB 7. The 
editor continues to process lines from IOCB 7 until an end-of- 
file error occurs. The IOTEST routine detects the EOF 
condition, sees that we are using IOCB 7 for ENTER, closes 
device 7, and jumps to SNX2 to reset the enter device 
(ENTDTD) to and print the READY message before restarting 
at the beginning of the editor. 

The LIST Statement 

The routine which simulates the LIST statement, XLIST, is 
actually another example of a language translator, complete 
with symbols and symbol-combining rules. XLIST translates 
the tokens generated by Atari BASIC back into the semi- 
English BASIC statements in ATASCII. This translation is a 
much simpler task than the one done by the pre-compiler, 
since XLIST can assume that the statement to be translated is 
syntactically correct. All that is required is to translate the 
tokens and insert blanks in the appropriate places. 

The List Device 

BASIC maintains a list device indicator, LISTDTD ($B5), 
similar to the enter device indicator discussed earlier. 
When a BASIC routine wants to output some data (an error 
message, for example), the I/O operation is done to the device 
(IOCB) specified in LISTDTD. 

During coldstart initialization and at various other times, 
LISTDTD is set to zero, representing IOCB 0, the editor, which 
will place the output on the screen. Routines such as XPRINT 
or XLIST can change the LIST device to indicate some other 
IOCB. Thus the majority of the BASIC routines need not be 
concerned about the output's destination. 

Remember that IOCB is always open to the editor, which 
gets input from the keyboard and outputs to the screen. IOCB 6 
is the S: device, the direct access to graphics screen, which is 
used in GRAPHICS statements. Atari BASIC uses IOCB 7 for 
I/O commands that allow different devices, like SAVE, LOAD, 
ENTER, and LIST. 

XLIST ($B483) 

The XLIST routine considers the output's destination in its 
initialization process and then forgets about it. It looks at the 
first expression in the tokenized line. If it is the < filespec > 

86 



Chapter Eleven 



string, XLIST calls a routine to open the specified device using 
IOCB 7 and to store a 7 in LISTDTD. All of XLIST's other 
processing is exactly the same, regardless of the LISTed data's 
final destination. 

XLIST marks its place in the Statement Table by calling a 
subroutine of XGOSUB to put a GOSUB type entry on the 
Runtime Stack. Then XLIST steps through the Statement Table 
in the same way that Execution Control does, using Execution 
Control's line parameters and subroutines. When XLIST is 
finished, Execution Control takes the entry off the Runtime 
Stack and continues. 

The XLIST routine, assuming it is to LIST all program 
statements, sets default starting and ending line numbers of 
(in TSLNUM) and $7FFF (in LELNUM). 

XLIST then determines whether line numbers were 
specified in the tokenized line that contained the LIST 
statement. XLIST compares the current index into the line 
(STINDEX) to the displacement to the next statement 
(NXTSTD). If STINDEX is not pointing to the next statement, 
at least one line number is specified. In this case, XLIST calls a 
subroutine of Execute Expression to evaluate the line number 
and convert it to a positive integer, which XLIST stores in 
TSLNUM as the starting line number. 

If a second line number is specified, XLIST calls Execute 
Expression again and stores the value in LELNUM as the final 
line to LIST. If there is no second line number, then XLIST 
makes the ending line number equal to the starting line 
number, and only one line will be LISTed. If no line numbers 
were present, then TSLNUM and LELNUM still contain their 
default values, and all the program lines will be LISTed. 

XLIST gets the first line to be LISTed by calling the 
Execution Control subroutine GETSTMT to initialize the line 
parameters to correspond to the line number in TSLNUM. If 
we are not at the end of the Statement Table, and if the current 
line's number is less than or equal to the final line number to be 
LISTed, XLIST calls a subroutine :LLINE to list the line. 

After LISTing the line, XLIST calls Execution Control's 
subroutines to point to the next line. LISTing continues in this 
manner until the end of the Statement Table is reached or until 
the final line specified has been printed. 

When XLIST is finished, it exits via XRTN at $B719, which 
makes the LIST statement the current statement again and then 
returns to Execution Control. 

87 



Chapter Eleven 



LIST Subroutines 

:LLINE ($B55C) 

The :LLINE routine LISTs the current line (the line whose 
address is in STMCUR). 

:LLINE gets the line number from the beginning of the 
tokenized line. The floating point package is called to convert 
the integer to floating point and then to printable ATASCII. The 
result is stored in the buffer indicated by INBUFF. :LLINE calls 
a subroutine to print the line number and then a blank. 

For every statement in the line, :LLINE sets STINDEX to 
point to the statement name token and calls the :LSTMT 
routine ($B590) to LIST the statement. When all statements 
have been LISTed, :LLINE returns to its caller, XLIST. 

:LSTMT($B590) 

The :LSTMT routine LISTs the statement which starts at the 
current displacement (in STINDEX) into the current line. This 
routine does the actual language translation from tokens to 
BASIC statements. 

:LSTMT uses two subroutines, :LGCT and :LGNT, to get 
the current and next token, respectively. If the end of the 
statement has been reached, these routines both pull the return 
address of their caller off the 6502 CPU stack and return to 
:LSTMT's caller, :LLINE. Otherwise, they return the requested 
token from the tokenized statement line. 

The first token in a statement is the statement name token. 
:LSTMT calls a routine which prints the corresponding 
statement name by calling :LSCAN to find the entry and 
:LPRTOKENtoprintit. 

In the discussion of the Program Editor we saw that an 
erroneous statement was given a statement name of ERROR 
and saved in the Statement Table. If the current statement is 
this ERROR statement or is REM or DATA, :LSTMT picks up 
each remaining character in the statement and calls PRCHAR 
($BA9F) to print the character. 

Each type of token is handled differently. :LSTMT 
determines the type (variable, numeric constant, string 
constant, or operator) and goes to the proper code to translate 
it. 

Variable Token. A variable token has a value greater than or 
equal to $80. When :LSTMT encounters a variable token, it 

88 



Chapter Eleven 



turns off the most significant bit to get an index into the 
Variable Name Table. :LSTMT asks the :LSCAN routine to get 
the address of this entry. :LSTMT then calls :LPRTOKEN 
($B535) to print the variable name. If the last character of the 
name is (, the next token is an array left parenthesis operator, 
and :LSTMT skips it. 

Numeric Constant Token. A numeric constant is indicated by 
a token of $0E. The next six bytes are a floating point number. 
:LSTMT moves the numeric constant from the tokenized line to 
FRO ($D4) and asks the floating point package to convert it to 
ATASCII. The result is in a buffer pointed to by INBUFF. 
:LSTMT moves the address of the ATASCII number to 
SRC ADR and tells :LPRTOKEN to print it. 

String Constant Token. A string constant is indicated by a 
token of $0F. The next byte is the length of the string followed 
by the actual string data. Since the double quotes are not stored 
with a string constant, :LSTMT calls PRCHAR ($BA9F) to print 
the leading double quote. The string length tells :LSTMT how 
many following characters to print without translation. 
:LSTMT repeatedly gets a character and calls PRCHAR to print 
it until the whole string constant has been processed. It then 
asks PRCHAR to print the ending double quote. 

Operator Token. An operator token is any token greater than 
or equal to $10 and less than $80. By subtracting $10 from the 
token value, :LSTMT creates an index into the Operator Name 
Table. :LSTMT calls :LSCAN to find the address of this entry. If 
the operator is a function (token value greater than or equal to 
$3D), :LPROTOKEN is called to print it. If this operator is not a 
function but its name is alphabetic (such as AND), the name is 
printed with a preceding and following blank. Otherwise, 
:LPRTOKEN is called to print just the operator name. 

:LSCAN ($B50C) 

This routine scans a table until it finds the translation of a token 
into an ATASCII name. A token's value is based on its table 
entry number; therefore, the entry number can be derived by 
modifying the token. For example, a variable token is created 
by machine-language ORing the table entry number of the 
variable name with $80. The entry number can be produced by 
ANDing out the high-order bit of the token. It is this entry 
number, stored in SCANT, that the :LSCAN routine uses. 



89 



Chapter Eleven 



The tables scanned by :LSCAN have a definite structure. 
Each entry consists of a fixed length portion followed by a 
variable length ATASCII portion. The last character in the 
ATASCII portion has the high-order bit on. Using these facts, 
:LSCAN finds the entry corresponding to the entry number in 
SCANT and puts the address of the ATASCII portion in 
SCRADR. 

:LPRTOKEN ($B535) 

This routine's task is to print the string of ATASCII characters 
whose address is in SCRADR. :LPRTOKEN makes sure the 
most significant bit is off (except for a carriage return) and 
prints the characters one at a time until it has printed the last 
character in the string (the one with its most significant bit on). 



90 



Chapter Twelve 



Atari Hardware 
Control Statements 



The Atari Hardware Control Statements allow easy access to 
some of the computer's graphics and audio capabilities. The 
statements in this group are COLOR, GRAPHICS, PLOT, 
POSITION, DRAWTO, SETCOLOR, LOCATE, and SOUND. 

XGR ($BA50) 

The GRAPHICS statement determines the current graphics 
mode. The XGR simulation routine executes the GRAPHICS 
statement. The XGR routine first closes IOCB 6. It then calls an 
Execute Expression subroutine to evaluate the graphics mode 
value and convert it to an integer. 

XGR sets up to open the screen by putting the address of a 
string "S:" into INBUFF. It creates an AUX1 and AUX2 byte 
from the graphics mode integer. XGR calls a BASIC I/O routine 
which sets up IOCB 6 and calls CIO to open the screen for the 
specified graphics mode. Like all BASIC routines that do I/O, 
XGR jumps to the IOTEST routine, which determines what to 
do next based on the outcome of the I/O. 

XCOLOR ($BA29) 

The COLOR statement is simulated by the XCOLOR routine. 
XCOLOR calls a subroutine of Execute Expression to evaluate 
the color value and convert it to an integer. XCOLOR saves this 
value (MOD 256) in BASIC memory location COLOR ($C8). 
This value is later retrieved by XPLOT and XDRAWTO. 

XSETCOLOR ($B9B7) 

The routine that simulates the SETCOLOR statement, 
XSETCOLOR, calls a subroutine of Execute Expression to 
evaluate the color register specified in the tokenized line. The 
Execute Expression routine produces a one-byte integer. If the 
value is not less than 5 (the number of color registers), 
XSETCOLOR exits via the Error Handling Routine at entry 
point ERVAL. Otherwise, it calls Execute Expression to get two 
more integers from the tokenized line. 

91 



Chapter Twelve 



To calculate the color value, XSETCOLOR multiplies the 
first integer (MOD 256) by 16 and adds the second (MOD 256). 
Since the operating system's five color registers are in 
consecutive locations starting at $2C4, XSETCOLOR uses the 
register value specified as an index to the proper register 
location and stores the color value there. 

XPOS ($BA16) 

The POSITION statement, which specifies the X and Y 
coordinates of the graphics cursor, is simulated by the XPOS 
routine. 

XPOS uses a subroutine of Execute Expression to evaluate 
the X coordinate of the graphics window cursor and convert it 
to an integer value. The two-byte result is stored in the 
operating system's X screen coordinate location (SCRX at $55). 
This is the column number or horizontal position of the cursor. 

XPOS then calls another Execute Expression subroutine to 
evaluate the Y coordinate and convert it to a one-byte integer. 
The result is stored in the Y screen coordinate location (SCRY at 
$54). This is the row number, or vertical position. 

XLOCATE ($BC95) 

XLOCATE, which simulates the LOCATE statement, first calls 
XPOS to set up the X and Y screen coordinates. Next it 
initializes IOCB 6 and joins a subroutine of XGET to do the 
actual I/O required to get the screen data into the variable 
specified. 

XPLOT ($BA76) 

XPLOT, which simulates the PLOT statement, first calls XPOS 

to set the X and Y coordinates of the graphics cursor. XPLOT 

gets the value that was saved in COLOR ($C8) and joins a PUT 

subroutine (PRCX at $BAA1) to do the I/O to IOCB 6 (the 

screen). 

XDRAWTO ($BA31) 

The XDRAWTO routine draws a line from the current X,Y 
screen coordinates to the X,Y coordinates specified in the 
statement. The routine calls XPOS to set the new X,Y 
coordinates. It places the value from BASIC'S memory location 
COLOR into OS location SVCOLOR ($2FB). XDRAWTO does 
some initialization of IOCB 6 specifying the draw command 
($11). It then calls a BASIC I/O routine which finishes the 



92 



Chapter Twelve 



initialization of IOCB 6 and calls CIO to draw the line. Finally, 
XDRAWTO jumps to the IOTEST routine, which will 
determine what to do next based on the outcome of the I/O. 

XSOUND($B9DD) 

The Atari computer hardware uses a set of memory locations to 
control sound capabilities. The SOUND statement gives the 
user access to some of these capabilities. The XSOUND 
routine, which simulates the SOUND statement, places fixed 
values in some of the sound locations and user specified values 
in others. 

The XSOUND routine uses Execute Expression to get four 
integer values from the tokenized statement line. If the first 
integer (voice) is greater than or equal to 4, the Error Handling 
Routine is invoked at ERVAL. 

The OS audio control bits are all turned off by storing a 
into $D208. Any bits left on from previous serial port usage are 
cleared by storing 3 in $D20F. 

The Atari has four sound registers (one for each voice) 
starting at $D200. The first byte of each two-byte register 
determines the pitch (frequency). In the second byte, the four 
most significant bits are the distortion, and the four least 
significant bits are the volume. 

The voice value mentioned earlier is multiplied by 2 and 
used as an index into the sound registers. The second value 
from the tokenized line is stored as the pitch in the first byte of 
one of the registers ($D200, $D202, $D204, or $D206), 
depending on the voice index. The third value from the 
tokenized line is multiplied by 16 and the fourth value is added 
to it to create the value to be stored as distortion/volume. The 
voice, times 2, is again used as an index to store this value in 
the second byte of a sound register ($D201, $D203, $D205, or 
$D207). The XSOUND routine then returns to Execution 
Control. 



93 



Chapter Thirteen 



External Data 
I/O Statements 



The external data I/O statements allow data which is not part of 
the BASIC source program to flow into and out of BASIC. 
External data can come from the keyboard, a disk, or a cassette. 
BASIC can also create external information by sending data to 
external devices such as the screen, a printer, or a disk. 

The INPUT and GET statements are the primary 
statements used for obtaining information from external 
devices. The PRINT and PUT statements are the primary 
statements for sending data to external devices. 

XIO, LPRINT, OPEN, CLOSE, NOTE, POINT and 
STATUS are specialized I/O statements. LPRINT is used to 
print a single line to the "P:" device. The other statements 
assist in the I/O process. 

XINPUT($B316) 

The execution of the INPUT statement starts at XINPUT 
($B316). 

Getting the Input Line. The first action of XINPUT is to 
read a line of data from the indicated device. A line is any 
combination of up to 255 characters terminated by the EOL 
character ($9B). This line will be read into the buffer located at 
$580. 

If the INPUT statement contained was followed by 

# < expression > , the data will be read from the IOCB whose 
number was specified by < expression > . If there was no 

# < expression > , IOCB will be used. IOCB is the screen 
editor and keyboard device (E:). If IOCB is indicated, the 
prompt character (?) will be displayed before the input line 
request is made; otherwise, no prompt is displayed. 

Line Processing. Once the line has been read into the 
buffer, processing of the data in that line starts at XINA 
($B335). The input line data is processed according to the 
tokens in the INPUT (or READ) statements. These tokens are 
numeric or string variables separated by commas. 

95 



Chapter Thirteen 



Processing a Numeric Variable. If the new token is a 
numeric variable, the CVAFP routine is called to convert the 
next characters in the input line to a floating point number. If 
this conversion does not report an error, and if the next input 
line character is a comma or an EOL, the floating point value is 
processed. 

The processing of a valid numeric input value consists of 
calling RTNVAR to return the variable and its new value to the 
Variable Value Table. 

If there is an error, INPUT processing is aborted via the 
ERRINP routine. If there is no error, but the user has hit 
BREAK, the process is aborted via XSTOP. If there is no abort, 
XINX ($B389) is called to continue with INPUT'S next task. 

Processing a String Variable. If the next statement token is 
a string variable, it is processed at XISTR ($B35E). This routine 
is also used by the READ statement. If the calling statement is 
INPUT, then all input line characters from the current character 
up to but not including the EOL character are considered to be 
part of the input string data. If the routine was called by READ, 
all characters up to but not including the next comma or EOL 
are considered to be part of the input string. 

The process of assigning the data to the string variable is 
handled by calling RISASN ($B386). If RISASN does not abort 
the process because of an error like DIMENSION TOO 
SMALL, XINX is called to continue with INPUT'S next task. 

XINX. The XINX ($B389) routine is entered after each variable 
token in an INPUT or a READ statement is processed. 

If the next token in the statement is an EOL, the 
INPUT/READ statement processing terminates at XIRTS 
($B3A1). XIRTS restores the line buffer pointer ($80) to the 
RAM table buffer. It then restores the enter device to IOCB 
(in case it had been changed to some other input device). 
Finally, XIRTS executes an RTS instruction. 

If the next INPUT/READ statement token is a comma, more 
input data is needed. If the next input line character is an EOL, 
another input line is obtained. If the statement was INPUT, the 
new line is obtained by entering XINO ($B326). If the statement 
was READ, the new line is obtained by entering XRD3 ($B2D0). 

The processing of the next INPUT/READ statement 
variable token continues at XINA. 



96 



Chapter Thirteen 



XGET ($BC7F) 

The GET statement obtains one character from some specified 
device and assigns that character to a scalar (non-array) 
numeric variable. 

The execution of GET starts at XGET ($BC7F) with a call to 
GIODVC. GIODVC will set the I/O device to whatever number 
is specified in the # < expression > or to IOCB zero if no 
# < expression > was specified. (If the device is IOCB (E:), the 
user must type RETURN to force E: to terminate the input.) 

The single character is obtained by calling 103. The 
character is assigned to the numeric variable by calling ISVAR1 
($BD2D). ISVAR1 also terminates the GET statement 
processing. 

PRINT 

The PRINT statement is used to transmit text data to an 
external device. The arguments in the PRINT statement are a 
list of numeric and/or string expressions separated by commas 
or semicolons. If the argument is numeric, the floating point 
value is converted to text form. If the argument is a string, the 
string value is transmitted as is. 

If an argument separator is a comma, the arguments are 
output in tabular fashion: each new argument starts at the next 
tab stop in the output line, with blanks separating the 
arguments. 

If the argument separator is a semicolon, the transmitted 
arguments are appended to each other without separation. 

The transmitted line is terminated with an EOL, unless a 
semicolon or comma directly precedes the statement's EOL or 
statement separator (:). 

XPRINT ($B3B6). The PRINT routine begins at XPRINT 
($B3B6). The tab value is maintained in the PTABW ($C9) cell. 
The cell is initialized with a value of ten during BASIC'S cold 
start, so that commas in the PRINT line cause each argument to 
be displaced ten positions after the beginning of the last 
argument. The user may POKE PTABW to set a different tab 
value. 

XPRINT copies PTABW to SCANT ($AF). SCANT will be 
used to contain the next multiple-of-PTABW output line 
displacement — the column number of the next tab stop. 

COX is initialized to zero and is used to maintain the 
current output column or displacement. 



97 



Chapter Thirteen 



XPRO. XPRINT examines the next statement token at XPRO 
($B3BE), classifies it, and executes the proper routine. 

# Token. If the next token is #, XPRIOD ($B437) is entered. 
This routine modifies the list device to the device specified in 
the #< expression > . XPRO is then entered to process the next 
token. 

, Token. The XPTAB ($B419) routine is called to process 
the , token. Its job is to tab to the next tab column. 

If COX (the current column) is greater than SCANT, we 
must skip to the next available tab position. This is done by 
continuously adding PTABW to SCANT until COX is less than 
or equal to SCANT. When COX is less than SCANT, blanks 
($20) are transmitted to the output device until COX is equal to 
SCANT. 

The next token is then examined at XPRO. 

EOL and : Tokens. The XPEOS ($B446) routine is entered 
for EOL and : tokens. If the previous token was a ; or , token, 
PRINT exits at XPRTN ($B458). If the previous token was not a ; 
or , token, an EOL character is transmitted before exiting via 
XPRTN. 

; Token. No special action is taken for the ; token except to 
go to XPRO to examine the next token. 

Numbers and Strings. If the next token is not one of the 

above tokens, Execute Expression is called to evaluate the 
expression. The resultant value is popped from the argument 
stack and its type is tested for a number or a string. 

If the argument popped was numeric, it will be converted 
to text form by calling CVFASC. The resulting text is 
transmitted to the output device from the buffer pointed to by 
INBUFF ($F3). XPRO is then entered to process the next token. 

If the argument popped was a string, it will be transmitted 
to the output device by the code starting at :XPSTR ($B3F8). 
This code examines the argument parameters to determine the 
current length of the string. When the string has been 
transmitted, XPRO is entered to process the next token. 

XLPRINT ($B464) 

LPRINT, a special form of the PRINT statement, is used to print 
a line to the printer device (P:). 



98 



Chapter Thirteen 



The XLPRINT routine starts at $B464 by opening IOCB 7 for 
output to the P: device. XPRINT is then called to do the 
printing. When the XPRINT is done, IOCB 7 is closed via 
CLSYS1 and LPRINT is terminated. 

XPUT ($BC72) 

The PUT statement sends a single byte from the expression in 
the PUT statement to a specified external device. 

Processing starts at XPUT ($BC72) with a call to GIODVC. 
GIODVC sets the I/O device to the IOCB specified in 
# < expression > . If a # < expression > does not exist, the 
device will be set to IOCB zero (E:). 

The routine then calls GETINT to execute PUT's expression 
and convert the resulting value to a two-byte integer. The least 
significant byte of this integer is then sent to the PUT device via 
PRCX. PRCX also terminates the PUT processing. 

XXIO ($BBE5) 

The XIO statement, a general purpose I/O statement, is 
intended to be used when no other BASIC I/O statement will 
serve the requirements. The XIO parameters are an IOCB I/O 
command, an IOCB specifying expression, an AUX1 value, an 
AUX2 value, and finally a string expression to be used as a 
filespec parameter. 

XIO starts at XXIO ($BBE5) with a call to GIOCMD. 
GIOCMD gets the IOCB command parameter. XIO then 
continues at XOP1 in the OPEN statement code. 

XOPEN ($BBEB) 

The OPEN statement is used to open an external device for 
input and/or output. OPEN has a # < expression > , the open 
type parameter (AUX1), an AUX2 parameter, and a string 
expression to be used as a filespec. 

OPEN starts at XOPEN at $BBEB. It loads the open 
command code into the A register and continues at XOP1. 

XOP1 . XOP1 continues the OPEN and XIO statement 
processing. It starts at $BBED by storing the A register into the 
IOCMD cell. Next it obtains the AUX1 (open type) and AUX2 
values from the statement. 

The next parameter is the filespec string. In order to insure 
that the filespec has a proper terminator, SETSEOL is called to 
place a temporary EOL at the end of the string. 



99 



Chapter Thirteen 



The XIO or OPEN command is then executed via a call to 
IOl. When IOl returns, the temporary EOL at the end of the 
string is replaced with its previous value by calling RSTSEOL. 

OPEN and XIO terminate by calling IOTEST to insure that 
the command was executed without error. 

XCLOSE($BC1B) 

The CLOSE statement, which closes the specified device, starts 
at XCLOSE ($BC1B). It loads the IOCB close command code 
into the A register and continues at GDVCIO. 

GDVCIO. GDVCIO ($BC1D) is used for general purpose 
device I/O. It stores the A register into the IOCMD cell, calls 
GIODVC to get the device from # < expression > , then calls 107 
to execute the I/O. When 107 returns, IOTEST is called to test 
the results of the I/O and terminate the routine. 

XSTATUS ($BC28) 

The STATUS statement executes the IOCB status command. 
Processing starts at XSTATUS ($BC28) by calling GIODVC to 
get the device number from #< expression > . It then calls 108 
with the status command in the A register. When 108 returns, 
the status returned in the IOCB status cell is assigned to the 
variable specified in the STATUS statement by calling ISVAR1. 
ISVAR1 also terminates the STATUS statement processing. 

XNOTE ($BC36) 

The NOTE statement is used specifically for disk random 
access. NOTE executes the Disk Device Dependent Note 
Command, $26, which returns two values representing the 
current position within the file for which the IOCB is open. 

NOTE begins at XNOTE at $BC36. The code loads the 
command value, $26, into the A register and calls GDVCIO to 
do the I/O operation. When GDVCIO returns, the values are 
moved from AUX3 and AUX4 to the first variable in the NOTE 
statement. The next variable is assigned the value from AUX5. 

XPOINT($BC4D) 

The POINT statement is used to position a disk file to a 
previously NOTEd location. Processing starts at XPOINT 
($BC4D). This routine converts the first POINT parameter to an 
integer and stores the value in AUX3 and AUX4. The second 
parameter is then converted to an integer and its value stored 



100 



Chapter Thirteen 



in AUX5. The POINT command, $25, is executed by calling 
GDIOl, which is part of GDVCIO. 

Miscellaneous I/O Subroutines 

IOTEST. IOTEST ($BCB3) is a general purpose routine that 
examines the results of an I/O operation. If the I/O processing 
has returned an error, IOTEST processes that error. 

IOTEST starts by calling LDlOSTA to get the status byte 
from the IOCB that performed the last I/O operation. If the byte 
value is positive (less than 128), IOTEST returns to the caller. 

If the status byte is negative, the I/O operation was 
abnormal and processing continues at SICKIO. 

If the I/O aborted due to a BREAK key depression, BRKBYT 
($11) is set to zero to indicate BREAK. If a LOAD was in 
progress when BREAK was hit, exit is via COLDSTART; 
otherwise IOTEST returns to its caller. 

If the error was not from IOCB 7 (the device BASIC uses), 
the error status value is stored in ERRNUM and ERROR is 
called to print the error message and abort program execution. 

If the error was from IOCB 7, then IOCB 7 is closed and 
ERROR is called with the error status value in ERRNUM — 
unless ENTER was being executed, and the error was an end- 
of-file error. In this case, IOCB 7 is closed, the enter device is 
reset to IOCB 0, and SNX2 is called to return control to the 
Program Editor. 

I/O Call Routine. All I/O is initiated from the routine starting 
at IOl ($BD0A). This routine has eight entry points, IOl 
through 108, each of which stores predetermined values in an 
IOCB. All IOn entry points assume that the X register contains 
the IOCB value, times 16. 

101 sets the buffer length to 255. 

102 sets the buffer length to zero. 

103 sets the buffer length to the value in the Y register plus 
a most-significant length byte of zero. 

104 sets the buffer length from the values in the Y, A 
register pair, with the A register being the most-significant 
value. 

105 sets the buffer address from the value in the INBUFF 
cell($F3). 

106 sets the buffer address from the Y, A register pair. The 
A register contains the most significant byte. 



101 



Chapter Thirteen 



107 sets the I/O command value from the value in the 
IOCMD cell. 

108 sets the I/O command from the value in the A register. 
All of this is followed by a call to the operating system CIO 

entry point. This call executes the I/O. When CIO returns, the 
general I/O routine returns to its caller. 



102 



Chapter Fourteen 



Internal I/O 
Statements 



The READ, DATA, and RESTORE statements work together to 
allow the BASIC user to pass predetermined information to his 
or her program. This is, in a sense, internal I/O. 

XDATA ($A9E7) 

The information to be passed to the BASIC program is stored in 
one or more DATA statements. A DATA statement can occur 
any place in the program, but execution of a DATA statement 
has no effect. 

When Execution Control encounters a DATA statement, it 
expects to process this statement just like any other. Therefore 
an XDATA routine is called, but XDATA simply returns to 
Execution Control. 

XREAD ($B283) 

The XREAD routine must search the Statement Table to find 
DATA. It uses Execution Control's subroutines and line 
parameters to do this. When XREAD is done, it must restore 
the line parameters to point to the READ statement. In order to 
mark its place in the Statement Table, XREAD calls a 
subroutine of XGOSUB to put a GOSUB-type entry on the 
Runtime Stack. 

The BASIC program may need to READ some DATA, do 
some other processing, and then READ more DATA. 
Therefore, XREAD needs to keep track of just where it is in 
which DATA statement. There are two parameters that provide 
for this. DATALN ($B7) contains the line number at which to 
start the search for the next DATA statement. DATAD ($B6) 
contains the displacement of the next DATA element in the 
DATALN line. Both values are set to zero as part of RUN and 
CLR statement processing. 

XREAD calls Execution Control's subroutine GETSTMT to 
get the line whose number is stored in DATALN. If this is the 
first READ in the program and a RESTORE has not set a 



103 



Chapter Fourteen 



different line number, DATALN contains zero, and GETSTMT 
will gel the first line in the program. On subsequent READs, 
GETSTM7' gets the last DATA statement that was processed by 
the previous READ. 

After getting its first line, XREAD calls the XRTN routine to 
restore Execution Control's line parameters. 

The current line number is stored in DATALN. XREAD 
steps through the line, statement by statement, looking for a 
DATA statement. If the line contains no DATA statement, then 
subsequent lines and statements are examined until a DATA 
statement is found. 

When a DATA statement has been found, XREAD inspects 
the elements of the DATA statement until it finds the element 
whose displacement is in DATAD. 

If no DATA is found, XREAD exits via the ERROOD entry 
point in the Error Handling Routine. Otherwise, a flag is set to 
indicate that a READ is being done, and XREAD joins XINPUT 
at :XINA. XINPUT handles the assignment of the DATA values 
to the variables. (See Chapter 13.) 

XREST ($B26B) 

The RESTORE statement allows the BASIC user to re-READ a 
DATA statement or change the order in which the DATA 
statements are processed. The XREST routine simulates 
RESTORE. 

XREST sets DATALN to the line number given, or to zero if 
no line number is specified. It sets DATAD to zero, so that the 
next READ after a RESTORE will start at the first element in the 
DATA line specified in DATALN. 



104 



Chapter Fifteen 



Miscellaneous 
Statements 



XDEG ($B261) and XRAD ($B266) 

The transcendental functions such as SIN or COS will work 
with either degrees or radians, depending on the setting of 
RADFLG ($FB). The DEG and RAD statements cause RADFLG 
to be set. These statements are simulated by the XDEG and 
XRAD routines, respectively. 

The XDEG routine stores a six in RADFLG. XRAD sets it to 
zero. These particular values were chosen because they aid the 
transcendental functions in their calculations. 

RADFLG is set to zero during BASIC'S initialization 
process and also during simulation of the RUN statement. 

XPOKE ($B24C) 

The POKE statement is simulated by the XPOKE routine. 
XPOKE calls a subroutine of Execute Expression to get the 
address and data integers from the tokenized line. XPOKE then 
stores the data at the specified address. 

XBYE ($A9E8) 

The XBYE routine simulates the BYE statement. XBYE closes all 
IOCBs (devices and files) and then jumps to location $E471 in 
the Operating System. This ends BASIC and causes the memo 
pad to be displayed. 

XDOS ($A9EE) 

The DOS statement is simulated by the XDOS routine. The 
XDOS routine closes all IOCBs and jumps to whatever address 
is stored in location $0A. This will be the address of DOS if 
DOS has been loaded. If DOS has not been loaded, $0A will 
point to the memo pad. 

XLET ($AAEO) 

The LET and implied LET statements assign values to 
variables. They both invoke the XLET routine, which consists 
of the Execute Expression routines. (See Chapter 7.) 



105 



Chapter Fifteen 



XREM ($A9E7) 

The REM statement is for documentation purposes only and 
has no effect on the running program. The routine which 
simulates REM, XREM, simply executes an RTS instruction to 
return to Execution Control. 

XERR($B91E) 

When a line containing a syntax error is entered, it is given a 
special statement name token to indicate the error. The entire 
line is flagged as erroneous no matter how many previously 
good statements are in the line. The line is then stored in the 
Statement Table. 

The error statement is processed just like any other. 
Execution Control calls a routine, XERR, which is one of the 
entry points to the Error Handling Routine. It causes error 17 
(EXECUTION OF GARBAGE). 

XDIM($B1D9) 

The DIMension statement, simulated by the XDIM routine, 
reserves space in the String/ Array Table for the DIMensioned 
variable . 

The XDIM routine calls Execute Expression to get the 
variable to be DIMensioned from the Variable Value Table. The 
variable entry is put into a work area. In the process, Execute 
Expression gets the first and second DIMension values and sets 
a default of zero if only one value is specified. 

XDIM checks to see if the variable has already been 
DIMensioned. If the variable was already DIMensioned, XDIM 
exits via the ERRDIM entry point in the Error Handling 
Routine. If not, a bit is set in the variable type byte in the work 
area entry to mark this variable as DIMensioned. 

Next, XDIM calculates the amount of space required. This 
calculation is handled differently for strings and arrays. 

DIMensioning an Array. XDIM first increments both 
dimension values by one and then multiplies them together to 
get the number of elements in the array. XDIM multiplies the 
result by 6 (the length of a floating point number) to get the 
number of bytes required. EXPAND is called to expand the 
String/ Array Table by that amount. 

XDIM must finish building the variable entry in the work 
area. It stores the first and second dimension values in the 
entry. It also stores the array's displacement into the 



106 



Chapter Fifteen 



String/ Array Table. It then calls an Execute Expression 
subroutine to return the variable to the Variable Value Table. 
(See Chapter 3.) 

DIMensioning a String. Reserving space for a string in the 
String/Array Table is much simpler. XDIM merely calls the 
EXPAND routine to expand by the user-specified size. 

XDIM must also build the Variable Value Table entry in the 
work area. It sets the current length to and the maximum 
length to the DIMensioned value. The displacement of the 
string into the String/ Array Table is also stored in the variable. 
XDIM then calls a subroutine of Execute Expression to return 
the variable entry to the Variable Value Table. (See Chapter 3.) 



107 



Chapter Sixteen 



Initialization 



When the Atari computer is powered up with the BASIC 
cartridge in place, the operating system does some processing 
and then jumps to a BASIC routine. Between the time that 
BASIC first gets control and the time it prints the READY 
message, initialization takes place. This initialization is called a 
cold start. No data or tables are preserved during a cold start. 

Initialization is repeated if things go terribly awry. For 
example, if there is an I/O error while executing a LOAD 
statement, BASIC is totally confused. It gives up and begins all 
over again with the COLDSTART routine. 

Sometimes a less drastic partial initialization is necessary. 
This process is handled by the WARMSTART routine, in which 
some tables are preserved. 

Entering the NEW statement, simulated by the XNEW 
routine, has almost the same effect as a cold start. 

COLDSTART ($A000) 

Two flags, LOADFLG and WARMFLG, are used to determine 
if a cold or warm start is required. 

The load flag, LOADFLG ($CA), is zero except during the 
execution of a LOAD statement. The XLOAD routine sets the 
flag to non-zero when it starts processing and resets it to zero 
when it finishes. If an I/O error occurs during that interval, 
IOTEST notes that LOADFLG is non-zero and jumps to 
COLDSTART. 

The warm-start flag, WARMFLG ($08), is never set by 
BASIC. It is set by some other routine, such as the operating 
system or DOS. If WARMFLG is zero, a cold start is done. If it 
is non-zero, a warm start is done. During its power-up 
processing, before BASIC is given control, OS sets WARMFLG 
to zero to request a cold start. During System Reset processing, 
OS sets the flag to non-zero, indicating a warm start is desired. 

If DOS has loaded any data into BASIC'S program area 
during its processing, it will request a cold start. 

The COLDSTART routine checks both WARMFLG and 
LOADFLG to determine whether to do a cold or warm start. If 
a cold start is required, COLDSTART initializes the 6502 CPU 



109 



Chapter Sixteen 



stack and clears the decimal flag. The rest of its processing is 
exactly the same as if the NEW statement had been entered. 

XNEW($A00C) 

The NEW statement is simulated by the XNEW routine. XNEW 
resets the load flag, LOADFLG, to zero. It initializes the zero- 
page pointers to BASIC'S RAM tables. It reserves 256 bytes at 
the low memory address for the multipurpose buffer and 
stores its address in the zero-page pointer located at $80. 
Since none of the RAM tables are to retain any data, their zero- 
page pointers ($82 through $90) are all set to low memory plus 
256. 

The Variable Name Table is expanded by one byte, which is 
set to zero. This creates a dummy end-of-table entry. 

The Statement Table is expanded by three bytes. The line 
number of the direct statement ($8000) is stored there along 
with the length (three). This marks the end of the Statement 
Table. 

A default tab value of 10 is set for the PRINT statement. 

WARMSTART ($A04D) 

A warm start is the least drastic of the three types of 
initialization. Everything the WARMSTART routine does is also 
done by COLDSTART and XNEW. 

The stop line number (STOPLN), the error number 
(ERRNUM), and the DATA parameters (DATALN and DATAD) 
are all set to zero. The RADFLG flag is set to zero, indicating 
that transcendental functions are working in radians. The 
break byte (BRKBYT) is set off and $FF is stored in TRAPLN to 
indicate that errors are not being trapped. 

All IOCBs (devices and files) are closed. 

The enter and list devices (ENTDTD and LISTDTD) are set 
to zero to indicate the keyboard and the screen, respectively. 

Finally, the READY message is printed and control passes 
to the Program Editor. 



110 



Part Two 



Accessing 
Atari BASIC 



-J 



Introduction to 
Part Two 



Congratulations! If you have read all of Part 1, you are through 
the hard stuff. In Part 2, we hope to teach you how to use at 
least some of the abundance of information presented in the 
Source Listing and in Part 1. In particular, we will show you 
how to examine the various RAM and ROM tables used by 
BASIC. 

The examples and suggestions will be written in Atari 
BASIC. But those of you who are true-blue assembly language 
fanatics should have little trouble translating the concepts to 
machine code, especially with the source listing to guide you. 

Would that we could present an example program or 
concept for each possible aspect of the BASIC interpreter, but 
space does not allow it — nor would it be appropriate. For 
example, although we will present here a program to list all 
keywords and token values used by BASIC, we will not explore 
the results (usually disastrous) of changing token values within 
a BASIC program. 

Part 2 begins with a pair of introductory chapters. If you are 
experienced at hexadecimal-to-decimal conversions and with 
the concepts of word and byte PEEKs and POKEs, you may 
wish to skip directly to Chapter 3. 



113 



Chapter One 



Hexadecimal 
Numbers 



The word hexadecimal means, literally, "of six and ten." It 
implies, however, a number notation which uses 16 as its base 
instead of 10. Hexadecimal notation is used as a sort of 
shorthand for the eight-digit binary numbers that the 6502 
understands. If Atari BASIC understood hexadecimal numbers 
and we all had eight fingers on each hand, there would be no 
need for this chapter. Instead, to use this book you have to 
make many conversions back and forth between hexadecimal 
("hex") and decimal notation. Many BASIC users have never 
had to learn that process. 

Virtually all the references to addresses and other values in 
this book are given in hexadecimal notation (or simply "hex" 
to us insiders). For example, we learn that the Atari BASIC 
ROM cartridge has $A000 for its lowest address and that 
location $80 contains a pointer to BASIC'S current LOMEM. 
But what does all that mean? 

First of all, if you are not familiar with 6502 assembly 
language, let me point out that there is a convention that a 
number preceded by a dollar sign ($80) is a hexadecimal 
number, even if it contains only decimal digits. Also, notice 
that in the Source Listing all numbers in the first three columns 
are hexadecimal, even though the dollar sign is not present. (To 
the right of those columns, though, only those numbers 
preceded by a dollar sign are in hex.) 

Now, suppose I wanted to look at the contents of location 
$A4AF (SNTAB in the listing). Realistically, the only way to 
look at a memory location from BASIC is via the PEEK function 
(and see the next chapter if you are not sure how to use PEEK 
in this situation). But BASIC'S language syntax requires a 
decimal number with PEEK — for instance, PEEK (15). 

Obviously, we need some way to convert from hexadecimal 
to decimal. Aside from going out and buying one of the 
calculators made just for this purpose, the best way is probably 
to let your computer help you. And the computer can help you 

115 



Chapter One 



even if you only understand BASIC. As an example, here's a 
BASIC program that will convert hex to decimal notation: 

10 DIM HEX$(23) ,NUM$(4) 

20 HEX$="@ABCDEFGHI#######JKLMNO" 

30 CVHEX=9000 

100 PRINT : PRINT "GIVE ME A HEX NUMBER 

110 INPUT NUM$ 

120 GOSUB CVHEX 

130 PRINT "HEX ";NUM$;" = DECIMAL " ; NUM 

140 GOTO 100 

9000 REM THE CONVERT HEX TO DECIMAL ROUTINE 

9010 NUM=0 

9020 FOR 1=1 TO LEN(NUM$) 

9030 NUM=NUM*16+ASC(HEX$(ASC(NUM$(I) )-47) )-64 

9040 NEXT I : RETURN 

Now, while this program might be handy for a few 
purposes, it would be much neater if we could simply use its 
capabilities anytime we wanted to examine or change a location 
(or its contents) referred to by a hex address or data. And so 
shall it be used. 

If we remove lines 100 through 140, inclusive, then any 
BASIC program which incorporates the rest of the program 
may change a hex number into decimal by simply 

1 . placing the ATASCII form of the hex number in the 
variable NUM$, 

2. calling the convert routine at line 9000 (via GOSUB 
CVHEX), and 

3. using the result, which is returned in the variable NUM. 

In the next chapter, we will immediately begin to make use 
of this routine. If you are not used to hex notation, you might 
do well to type in and play with this program before 
proceeding. 

Finally, before we leave this subject, let's examine a routine 
which will allow us to go the other way — that is, convert 
decimal to hex: 

40 DIM DEC$(16) :DEC$="0123456789ABCDEF" 

50 CVDEC=9100 

100 PRINT : PRINT "GIVE ME A DECIMAL NUMBER 



116 



Chapter One 



110 INPUT DEC:NUM=DEC 

120 GOSUB CVDEC:REM ' NUM ' is destroyed by this 

130 PRINT DEC;" Decimal = ";NUM$;" Hex" 

140 GOTO 100 

9100 REM CONVERT DECIMAL TO HEX ROUTINE 

9110 DIV=4096 

9120 FOR 1=1 TO 4 

9130 N=INT(NUM/DIV) :NUM$(I, I)=DEC$ (N+l ) 

9140 NUM=NUM-DIV*N:DIV=DIV/16 

9150 NEXT I 

9160 RETURN 

These lines are meant to be added to the previous program, 
though they can be used alone if you simply add this line: 

10 DIMNUM$(4) 

We will use portions of these programs in later chapters, 
but we may compress some of the code into fewer lines simply 
to save wear and tear on our fingers. If you study these 
routines, you'll recognize them in their transformed versions. 



117 



Chapter Two 



PEEKing and 
POKEing 



In contrast to languages which include direct machine 
addressing capability, like "C" and Forth, and in contrast to 
"school" languages like Pascal and Fortran, which specifically 
prevent such addressing, BASIC provides a sort of halfway 
measure in machine accessibility. 

POKE is a BASIC statement. Its syntax is 
POKE < address > , < data > . Naturally, both < address > and 
< data > may be constants, variables, or even full-blown 
expressions: 

POKE 82,0: REM change left screen margin to zero 
produces the same result as 

LEFTMARGIN = 82:POKE LEFTMARGIN,0 

PEEK, on the other hand, is a BASIC function. It cannot 
stand alone as a statement. To use PEEK, we either PRINT the 
value (contents) of a PEEKed location, assign a PEEKed value 
to a variable, or test the value for some condition: 

POKE 82, PEEK(82) + 1 : REM move the left margin in a 
space 

PRINT PEEK(106) : REM where is the top of system 
memory? 

IF PEEK(195) = 136 THEN PRINT "End of File" 

In the first example, the number POKEd into 82 will be 
whatever number was stored before, plus 1. As explained in 
Part 1, the PEEK function is executed before the POKE. 

An aside: Just where did I get those addresses I used in the 
PEEKs and POKEs? One way to find them is to peruse the 
listings of Atari's operating system, available in Atari's 
technical manuals set, and the listing of BASIC in this book. 
Another way would be to use a book (like COMPUTE! Books' 
Mapping the Atari) or a reference card designed specifically to 
tell you about such addresses. 

And one more thing to consider before moving on. If we 
counted all of the bit patterns possible in a single 8-bit byte (like 

119 



Chapter Two 



01010101, 11110000, and 00000001, where each 1 or represents 
a single on or off bit), we would discover that there are 256 
unique combinations, ranging in value from to 255. Since 
each memory location can hold only one byte, it is not 
surprising to learn that the PEEK function will always return a 
number from to 255 ($00 to $FF). Similarly, BASIC will only 
POKE a data value that is an integer from to 255. In fact, 
BASIC will convert any data to be POKEd to an integer 
number, rounding off any fractional parts. 

So far so good. But suppose we want to examine a location 
which is actually a two-byte word, such as the line number 
where the last TRAPped error occurred, stored starting at 
location $BA hex or 186 decimal. PEEK only lets us look at one 
byte at a time. How do we look at two bytes? Simple: one byte 
at a time. 

In most cases, words in a 6502-based machine are stored in 
memory with the least significant byte stored first. This means 
that the second byte of each word is a count of the number of 
256 's there are in its value, and the first byte is the leftovers. 
(Or we can more properly say that the first byte contains "the 
word's value modulo 256.") Confused? Let's try restating that. 

In decimal arithmetic, we can count from to 9 in a single 
digit. To go beyond 9, we have a convention that says the digit 
second from the right represents the number of 10's in the 
number, and so on. 

If we consider bytes to be a computer's digits, which in 
many ways they are, and if we remember that each byte may 
represent any number from to 255 (or $00 to $FF), then it is 
logical to say that the next byte is a count of the number of 256's 
in the number. The only thing illogical is that the higher byte 
comes after the lower byte (like reading 37 as "7 tens and 3 
ones" instead of what we are used to). 

Some examples might help: 



a 6502 word 


as written 


think of 


decima 


in memory 


in assembler 


it as 


value 


0100 


$0001 


0*256 +1 


1 


00 01 


$0100 


1*256 +0 


256 


02 04 


$0402 


4*256 +2 


1026 


FFFF 


$FFFF 


255*256 +255 


65535 



So let's examine that error line location: 
PRINT PEEK(186) + 256 * PEEK(187) 

120 



Chapter Two 



Do you see it? Since the second byte is a count of the number of 
256's in the value, we must multiply it by 256 to calculate its 
true value. 

Now, in the case of line numbers, it is well and good that 
we print out a decimal value, since that is how we are used to 
thinking of them. But suppose you wished to print out some of 
BASIC'S tables? You might very well wish to see the hex 
representations. The program presented here allows you to 
specify a hex address. It then presents you with the contents of 
the byte and the word found at that address, in both decimal 
and hex form. 

10 DIM HEX$(23) ,NUM$(4) 

20 HEX$="@ABCDEFGHI ####### JKLMNO" 

30 CVHEX=9000 

40 DIM DEC$(16) :DEC$="0123456789ABCDEF" 

50 CVDEC=9100 

100 PRINT : PRINT "WHAT ADDRESS TO VIEW "; 

110 INPUT NUM$: PRINT 

120 PRINT "Address ";NUM$;" contains:" 

130 GOSUB CVHEX : ADDR=NUM 

140 NUM=PEEK(ADDR) : GOSUB CVDEC 

150 PRINT , "byte " ; PEEK( ADDR) ; " - $";NUM$(3) 

160 WORD=PEEK(ADDR)+256*PEEK(ADDR+l ) 

170 NUM=WORD: GOSUB CVDEC 

180 PRINT , "word ";WORD;" = $";NUM$ 

190 GOTO 100 

9000 REM THE CONVERT HEX TO DECIMAL ROUTINE 

9010 NUM=0 

9020 FOR 1=1 TO LEN(NUM$) 

9030 NUM=NUM*16+ASC(HEX$(ASC(NUM$(I) )-47) )-64 

9040 NEXT I: RETURN 

9100 REM CONVERT DECIMAL TO HEX ROUTINE 

9110 DIV=4096 

9120 FOR 1=1 TO 4 

9130 N=INT(NUM/DIV) :NUM$(I, l)=DEC$(N+l ) 

9140 NUM=NUM-DIV*N:DIV=DIV/16 

9150 NEXT I 

9160 RETURN 

You may have noticed that lines 10 through 50 and lines 
9000 to the end are the same as those used in the example 



121 



Chapter Two 



programs in the last chapter. And did you see line 160, where 
we obtained the word value by multiplying by 256? 

As the last point of this chapter, we need to discuss how to 
change a word value. Obviously, in Atari BASIC we can't POKE 
both bytes of a word at once any more than we could retrieve 
both bytes at once (although BASIC A+ can, by using the 
DPOKE statement and DPEEK function). So we must invent a 
mechanism to do a double POKE. 

Given that the variable ADDR contains the address at 
which we wish to POKE a word, and given that the variable 
WORD contains the value (in decimal) of the desired word, the 
following code fragment will perform the double POKE: 

POKE ADDR + l,INT(WORD/256) 

POKE ADDR, WORD-256*PEEK( ADDR + 1) 

This is kind of sneaky code, but calculating the most 
significant byte and POKEing the value in byte location 
ADDR + 1 first allows us to also use it as a kind of temporary 
variable in calculating the least significant byte. By PEEKing the 
location that already holds the high-order byte, we can subtract 
it from the original value. The remainder is WORD modulo 256 
— the low-order byte. 

And that's about it. Hopefully, if you were not familiar 
with PEEK and POKE before, you now at least will not 
approach their use with too much caution. Generally, PEEKs 
will never harm either your running program or the machine, 
but don't be surprised if a stray POKE or two sends your 
computer off into never-never land. After all, you may have 
just told BASIC to start putting your program into ROM, or 
worse. 

On the other hand, if you have removed your diskettes and 
turned off your cassette recorder, the worst that can happen 
from an erring POKE is that you'll have to turn the power off 
and back on again. So have at it. Happy PEEKing and 
POKEing. 



122 



Chapter Three 



Listing Variables 

in Use 



Chapter 3 of Part 1 described the layout of the Variable Name 
Table and the Variable Value Table. In particular, we read that 
the Variable Name Table was built in a very simple fashion: 
Each new variable name, as it is encountered upon program 
entry, is simply added to the end of the list of names. The most 
significant bit of the last character of the name is turned on, to 
signal the end of that name. The contents of VNTP point to the 
beginning of the list of names, and the content of VNTD is the 
address of the byte after the end of the list. 

Now, what does all that mean? What does it imply that we 
can do? Briefly, it implies that we can look at BASIC'S memory 
and find out what variable names are in current use. Here's a 
program that will do exactly that: 

32700 QQ=128:PRINT QQ, 

32710 FOR Q=PEEK(130)+256*PEEK(131) TO PE 

EK(132)+256*PEEK(133)-1 
32720 IF PEEK(Q)<128 THEN PRINT CHR$(PEEK 

(Q)) ; :NEXT Q : STOP 
32730 PRINT CHR$ (PEEK(Q ) -128 ) : QQ=QQ+1 : PRI 

NT QQ, :NEXT Q : STOP 

Actually, this is not so much a program as it is a program 
fragment. It is intended that you will type NEW, type in the 
above fragment, and then LIST the fragment to a disk file (LIST 
"D:LVAR") or to a cassette (LIST "C:"). Then type NEW again 
and ENTER or LOAD the program whose variables you want 
to list. Finally, use ENTER to re-enter the fragment from disk 
(ENTER "D:LVAR") or cassette (ENTER "C:"). Then type 
GOTO 32700 to obtain your Variable Name Table listing. 

Of course, if you had OPENed a channel to the printer 
(OPEN #1,8,0,"P:"), you could change the PRINTs to direct 
the listing to the printer (PRINT #1; CHR$ ( < expression > ) ) . 



123 



Chapter Three 



How does the fragment work? The reason for the start and 
end limits for the FOR loop are simple: word location 130 ($82) 
contains the pointer to the beginning of the Variable Name 
Table and word location 132 ($84) contains the pointer to the 
end of that same table, plus 1. So we simply traipse through 
that table, printing characters as we encounter them — except 
that when we encounter a character with its most significant bit 
on (IF PEEK(Q) > 127), we turn off that bit before printing it and 
start the next name on a new line. 

Notice that we use the variable QQ to allow us to print out 
the token value for each variable name. We will use this 
information in some later chapters. 

Also note that the variable names QQ and Q will appear in 
your variable name listing. Sorry. We can write a program 
which would accomplish the same thing without using 
variables, but it would be two or three times as big and much 
harder to understand. Of course, if you consistently use certain 
variable names, such as J and / in FOR-NEXT loops, you could 
use those names here instead, thus not affecting the count of 
variables in use. 

Incidentally, the STOP at the end of the third line should be 
unnecessary, since the table is supposed to end with a 
character with its upper bit on. But I've learned not to take 
chances — things don't always go as they're supposed to. 



124 



■■■w Chapter Four 

Variable 
Values 



In this chapter, we will show how you can determine the value 
of any variable by inspecting the Variable Value Table. Actually, 
in many respects this is a waste of effort. After all, if I need to 
know the value of the variable TOTAL, I can just type PRINT 
TOTAL. 

But this book is supposed to be a guide, and there are a few 
uses for this information, particularly in assembly language 
subroutines, and it is instructive in that it gives us an inkling of 
what BASIC goes through to evaluate a variable reference. 

It will probably be better to present the program first, and 
then explain what it does. Before doing so, though, note that 
the program fragment expects you to give it a valid variable 
token (128 through 255). No checks are made on the validity of 
that number, since we are all intelligent humans here and since 
we want to save program space. Enough. The program: 

32500 PRINT : PRINT "WHAT VARIABLE NUMBER 

" ; : INPUT Q 
32505 Q=PEEK(134)+256*PEEK(135)+(Q-128)* 

8 
32510 PRINT : PRINT "VARIABLE NUMBER " ; PE 

EK(Q+1), 
32515 ON INT(PEEK(Q)/64) GOTO 32600,3265 


32520 PRINT "IS A NUMBER, ": PRINT , "VALU 

E "; 
32525 QEXP=PEEK(Q+2) : IF QEXP>127 THEN PR 

INT " - " ; : QEXP=QEXP- 1 2 8 
32 530 QNUM=0:FOR QQ=Q+3 TO Q+7 
32535 QNUM=QNUM* 1 00+PEEK ( QQ ) -6 * INT ( PEEK ( 

QQ)/16):NEXT QQ 
32540 QEXP=QEXP-68: IF QEXP=0 THEN 32555 
32545 FOR QQ=QEXP TO SGN(QEXP) STEP -SGN 

(QEXP) 

125 



Chapter Four 



32 550 QNUM=(QEXP>0)*QNUM*100+(QEXP<0)*QN 

UM/ 100: NEXT QQ 
32555 PRINT QNUM:PRINT :GOTO 32500 
32570 IF PEEK(Q)/2<>INT(PEEK(Q)/2) THEN 

32580 
32575 PRINT , "AND IS NOT YET DIMENSIONED 

": POP: GOTO 32500 
32580 PRINT /'ADDRESS IS " ; PEEK(Q+2 ) +256 

*PEEK ( Q+3 ) : RETURN 
32600 PRINT "IS AN ARRAY, ":GOSUB 32570 
32610 PRINT , "DIM 1 IS " ; PEEK(Q+4 )+256*P 

EEK(Q+5) 
32615 PRINT , "DIM 2 IS " ; PEEK(Q+6 ) +256*P 

EEK(Q+7) 
32620 GOTO 32500 

32650 PRINT "IS A STRING, ":GOSUB 32570 
32660 PRINT , "LENGTH IS " ; PEEK(Q+4 )+256* 

PEEK(Q+5) 
32665 PRINT ,"{3 SPACES}DIM IS ";PEEK(Q+ 

6)+256*PEEK(Q+7) 
32670 GOTO 32500 

Did you get lost in all of that? I got lost several times as I 
wrote it, but it seems to work well. Shall we discuss it? 

The first place where confusion may arise is when I ask you 
to give a variable token from 128 to 255, and then reveal that 
the entry in the Variable Value Table thinks variable numbers 
range from to 127. Actually, there is no anomaly here. The 
variable token that you input is the token value of the variable 
in your program. The number in the table is its relative 
position. The numbers differ only in their uppermost bit. 

The program uses the number you specify to form an 
address of an entry somewhere within the Variable Value 
Table. It then displays the internal variable number and 
examines the flag byte of the variable entry. Recall that the 
uppermost bit ($80, or 128) of the flag byte is on, if this variable 
is a string. The next bit ($40, or 64) is on if the variable is an 
array. If neither is on, the variable is a normal floating point 
number (or scalar, as it is sometimes called, to distinguish it 
from a floating point array). All this is decided and acted upon 
inline 32515. 



126 



Chapter Four 



Before examining what happens if the number is a scalar, 
let's look at strings and arrays. Both start out (lines 32600 and 
32650) by identifying themselves and calling a subroutine 
which determines if the variable has been DIMensioned yet. If 
not, the subroutine tells us so, removes the GOSUB entry from 
the stack, and starts the whole shebang over again. If the 
variable is DIMensioned, though, we print its address before 
returning. Note that the address printed is the relative address 
within the String/ Array Table. 

If the DIMension check subroutine returns, both string and 
array variables have their vitals printed out before the program 
asks you for another variable number. In the case of a string, 
we see the current length (as would be obtained by the LENgth 
function) and its dimension. For an array, we see both 
dimensions. Note that array dimensions here are always one 
greater than the user program specified, so that a zero 
dimension value means "this dimension is unused." 

Point of interest: this program will never print a zero for an 
array dimension. Why? Because Atari BASIC never places a 
zero in either dimension when the DIM statement is executed. 
In a way, this is a "feature" (a feature is a documented bug). It 
implies that we may code DIM XX(7) and yet use something 
like PRINT XX(N,0). In other words, a singly dimensioned 
array in Atari BASIC is exactly equivalent to a doubly 
dimensioned array with a as the second subscript in the DIM 
statement. 

Back to the listing. Fairly straightforward up until now. But 
look what happens if the variable is a scalar, a single floating 
point number. 

First, we obtain the exponent byte; if its upper bit is on, the 
number is negative, so we print the minus sign before turning 
the bit off. 

Second, we must loop through the five bytes of the 
mantissa, accumulating a value. The really strange part here is 
line 32535, so let's examine it closely. As we get each byte, we 
must multiply what we have gotten so far by 100 (remember, 
floating point numbers are in BCD format, so each byte 
represents a power of 100). Then, what we really want to do is 
add in 10 times the higher digit in the byte, plus the lower 
digit. We could have gotten those numbers as follows: 

NEWBCDVALUE = OLDBCDVALUE*100 
HIGHER = INT(PEEK(QQ)/16) 

127 



Chapter Four 



LOWER = PEEK(QQ)-16*HIGHER 

BYTEVALUE = 10*HIGHER + LOWER 

NEWBCD VALUE = NEWBCD VALUE + BYTEVALUE 

OLDBCDVALUE = NEWBCD VALUE 

Hopefully, your algebra is up to understanding how line 
32535 is just a simplification of all that. If not, don't worry 
about it. It works. 

But we still haven't accounted for the exponent. Now, 
exponents in the Atari floating point format are powers of 100 
in "excess 64" notation, which simply means that you subtract 
64 from the exponent to get the real power of 100. But wait! The 
implied decimal point is all the way to the left of the number. 
So we must bias our "excess 64" by the five multiplies-by-100 
we did in deriving the BCD value. All that is done in line 32540. 

Finally, we simply count the exponent down to one or up 
to minus one, depending on what it started at. And line 32545 
is tricky, but not too much so. I will leave its inner workings as 
an exercise for you, the reader. 

And, hard though it may be to believe, we arrive at line 
32555 with the number in hand. Then we PRINT it. 

Did we really have to go through all that? Not really, but 
perhaps it gives you an idea of what BASIC'S GETTOK routine 
($AB3E) does when it encounters a variable name. 

Finally, to test all this out, you should type it in, LIST it to 
disk or cassette, use NEW, and then enter or load your favorite 
program. Finally, re-ENTER this program fragment from disk 
or cassette and type GOTO 32500. Just for fun, you might try 
finding the variable values for the following program: 

10 A = 12.34567890 : B = 9876543210 

20 C = 0.0000556677 

30 GOTO 60 

40 D$ = "WILL NEVER BE EXECUTED" 

50 E(7) = 1 

60 DIM F$(30), G$(40), H(9,17), J(7) 

70 G$="ONLY THIS STRING WILL HAVE LENGTH" 

Type this little guy in, ENTER the variable value printer, 
and RUN the whole thing. Answer the variable number 
prompt with numbers from 128 to 135 and see what you get. 
It's interesting! 



128 



Chapter Five 



Examining the 
Statement Table 



If you will recall, Chapter 3 in Part 1 discussed the various user 
tables that existed in Atari BASIC'S RAM memory space. 
Specifically, it discussed the Variable Name Table, Variable 
Value Table, Statement Table, String/ Array Table, and Runtime 
Stack. 

In the last two chapters, we investigated the Variable Name 
Table and the Variable Value Table, showing how Atari BASIC 
can examine itself. So what is more logical than to now use 
Atari BASIC to display the contents of the Statement Table? 

While we could write a program that would examine the 
tokenized program and produce source text, there is little 
incentive to do so. The task would be both very difficult and 
very redundant: BASIC'S LIST command performs the same 
task very nicely, thank you. 

What we can do, though, is write a program which will 
show the actual hex tokens used in a logical and almost 
readable form. Again, let's look at the program before 
decoding what it does. 

10 DIM NUM$(4) 

40 DIM DEC$(16) :DEC$="0123456789ABCDEF" 

50 CVDEC=9100 

100 GOTO 32000 

110 ERROR- THIS IS AN ERROR LINE 

120 DATA AND, THIS, IS, DATA, 1,2,3 

130 REM LINES 110 TO 130 ARE FOR DEMONST 

RATION PURPOSES ONLY 
9100 REM CONVERT DECIMAL TO HEX 
9110 DIV=4096 
9120 FOR 1=1 TO 4 

9130 N=INT(NUM/DIV) :NUM$ ( I , I )=DEC$ (N+l ) 
9140 NUM=NUM-DIV*N:DIV=DIV/l6 
9150 NEXT I 
9160 RETURN 



129 



Chapter Five 



32000 QQ=PEEK(136)+256*PEEK(137) 

32010 Q=PEEK(QQ)+256*PEEK(QQ+1) :QS=QQ:QQ 

=QQ+3 
32015 IF Q>32767 THEN PRINT " — END — ":ST 

OP 
32020 QL=PEEK(QQ-1)+QS: PRINT "LINE NUMBE 

R ";Q,"LINE LENGTH ";PEEK(QQ-1) 
32030 QT=PEEK(QQ+1) : PRINT "{2 SPACES }STM 

T LENGTH "; PEEK (QQ) , "STMT CODE ";P 

EEK(QQ+1) 
32040 Q=PEEK(QQ)+QS:QQ=QQ+2 
32050 IF QQ<Q THEN 32080 
32060 IF Q<QL THEN PRINT : GOTO 32030 
32070 PRINT :GOTO 32010 
32080 IF QT>1 AND QT<55 THEN 32120 
32090 PRINT "{2 SPACES }UNTOKENI ZED: :" ; 
32100 PRINT CHR$(PEEK(QQ) ) ; :QQ=QQ+1:IF Q 

Q<Q THEN 32100 
32110 PRINT :GOTO 32010 
32120 NUM=PEEK(QQ) :GOSUB CVDEC 
32125 IF PEEK(QQ)>127 THEN PRINT " V=";N 

UM$(3) :GOTO 32200 
32130 IF PEEK(QQ)>15 THEN PRINT " ";NUM$ 

(3) ; :GOTO 32200 
32140 IF PEEK(QQ)=14 THEN GOTO 32170 
3 2150 QQ=QQ+1:QN=PEEK(QQ) :NUM=QN:GOSUB C 

VDEC 
32155 PRINT " S, " ;NUM$ ( 3 );"=";: IF QN=0 T 

HEN 32200 
32160 FOR QQ=QQ+1 TO QQ+QN-1 : PRINT CHR$ ( 

PEEK ( QQ ));: NEXT QQ : GOTO 32190 
32170 PRINT " N="; 
32180 FOR QQ=QQ+1 TO QQ+5 :NUM=PEEK(QQ ) :G 

OSUB CVDEC: PRINT NUM$ ( 3 ) ; :NEXT QQ 
32190 QQ=QQ-1: PRINT 
32200 QQ=QQ+1:IF QQ<Q THEN 32120 
32210 PRINT :IF QQ<QL THEN 32030 
32220 PRINT : GOTO 32010 

Now, even if you don't want to type all that in, there are a 
few points to be made about it. First, note that lines 10 through 
50 and 9100 through 9160 are the decimal-to-hex converter from 

130 



Chapter Five 



Chapter 2. Then, let's start with line 32000 and do a functional 
description, with the line numbers denoting the portion we are 
examining. 

32000. Decimal 136 is hex $88, the location of STMTAB, the 
pointer to the user's program space. 

32010, 32020. In each line, the first two bytes are the line 
number; the next byte is the line length (actually, the offset to 
next line). Remember, line 32768 is actually the direct 
statement. 

32030, 32040. Within a line, each statement begins with a 
statement length ( the offset to the next statement from 
the beginning of the line) and a statement token. 

32050-32070. Boundary conditions are checked for. 

32080-32110. REM becomes statement token 0, DATA is 
token 1 and the error token is 55 ($37). All three of them simply 
store the user's input unchanged. 

32120. Remember, any token with its upper bit on 
indicates a variable number token. They really don't need to be 
special cased in this program, but we do so for readability. 

32130. Operator tokens have values of 16 to 127 ($10 to 
$7F). 

32140-32160. For string constants (also called string literals), 
we simply print out the string length and its contents (the 
characters between the quote signs). 

32170-32180. For numeric constants, we simply print the 
hex values of all six bytes. 

32190-32200. Clean-up. We ensure that we return for all 
remaining tokens (if any) in each statement and for all 
remaining statements (if any) in each line. 

Observe the FOR-NEXT loop controls in line 32180. Why 
QQ + 1 TO QQ + 5 if we want six values printed out? Ah, but 
this is a trick. Note that the loop termination value (QQ + 5) 
involves the loop variable (QQ). The problem is, though, that 
the loop variable is changed by the prior implied assignment 
(QQ = QQ + 1) when the assignment takes place — which is, of 
course, before the determination of the value of "QQ + 5" takes 
place. 

In other words, by the time we are ready to evaluate 
QQ + 5, the variable QQ has already been changed from its 
original value to its new, loop controlling value (QQ + 1). 

Quite possibly, the proper general solution to using a FOR 
loop's variable in its own termination (or STEP) values is to 



131 



Chapter Five 



assign it to a temporary variable, thusly: 

QTEMP = QQ : FOR QQ = QTEMP + 1 TO QTEMP + 6 

Did you notice that line 32160 actually has the same 
problem? Notice that we solved it there by adding -1 to the 
termination value to compensate for the + 1 in the initialization 
assignment. 

One last comment before leaving the subject of strange 
FOR-NEXT loops. In Atari BASIC (and, indeed, in virtually all 
microcomputer BASICs), the termination (TO) value and the 
STEP value are determined when the FOR statement is first 
executed and are NOT changeable. Example: 

10 X=7:Y=2 

20 FOR I = 1 TO X STEP Y 

30 X = X+l 

40 Y = Y+X 

50 NEXT I 

This FOR loop will execute exactly four times (I = 1, 3, 5, 
and 7). The fact that X and Y change within the loop has no 
effect on the actual loop execution. 



132 



Chapter Six 



Viewing the 
Runtime Stack 



The Runtime Stack is the last of the user RAM tables that we 
will discuss in Part 2. 

Perhaps you noticed that we left out a discussion of the 
String/ Array Table in Part 2. The omission was on purpose: 
there seems little purpose in PEEKing the contents of this table 
when BASIC'S PRINT statement does an admirable job of 
letting you see all variable values. However, if you are so 
inclined, you could use the general purpose memory PEEKer 
program of Chapter 2 to view any portion of any memory, 
including the String/ Array Table. 

On the other hand, looking at the Runtime Stack is kind of 
fun and enlightening. And the program we will present here 
might even find use on occasion. If you are having trouble 
tracing a program's flow, through various GOSUBs and/or 
FOR loops, simply drop in the routine below and GOSUB to it 
at an appropriate place in your program. It will print out a LIFO 
(Last In, First Out) listing of all active GOSUB calls and FOR- 
NEXT loop beginnings. 

10 FOR J=l TO 3 

20 GOSUB 30 

30 FOR K=l TO 5 

40 GOSUB 50 

50 JUNK=7:FOR Q=l TO 2: GOSUB 32400 

32400 QQ=PEEK(144)+256*PEEK(145) 

32410 IF QQ<=PEEK(142)+256*PEEK(143) THE 

N PRINT " — END OF STACK — " : STOP 
32420 PRINT "AT LINE " ; PEEK(QQ-3 ) +256*PE 

EK(QQ-2); 
32430 PRINT ", OFFSET " ; PEEK (QQ-1 ) ; 
32440 IF PEEK(QQ-4)=0 THEN PRINT ", GOSU 

B" :QQ=QQ-4:GOTO 32410 
32450 PRINT ", FOR (#"; PEEK(QQ-4 );")": QQ 

=QQ-16:GOTO 32410 

133 



Chapter Six 



The first thing you might notice about this little routine is 
that, in contrast to all the programs we have used so far, it 
examines its portion of user RAM backward. That is, it starts 
at the top (high address) of the Runtime Stack area and works 
downward toward the bottom. 

Again, nothing surprising. If you will recall the description 
of entries on this stack (pages 18-19 and 133-34), you will 
remember that every entry, whether a GOSUB or FOR, has a 
four-byte header. And, while FOR statements also have twelve 
bytes of termination and step value added, the four bytes are 
always at the top of each entry — they are the last items put on 
the stack. 

Thus, we start at the top of the stack and examine four 
bytes. If the type byte is zero, it is a GOSUB entry, and all we 
must do is display the line number and statement offset. If we 
remove the four-byte header by subtracting 4 from our stack 
pointer, we are ready to examine the next entry. 

In the case of a FOR entry, we similarly display the line 
number and statement offset. However, each FOR entry also 
has a variable token associated with it, so we also display that 
token's value. With the variable name lister of Chapter 2, you 
can find out which variable is controlling this FOR loop. 
Finally, note that after displaying a FOR loop entry, we remove 
sixteen bytes (the four-byte header and the two six-byte 
floating point values) in preparation for the next entry. 

Incidentally, lines 10 through 50 are present as examples 
only. Add lines 32400 to 32450 to your own programs and see 
where you've come from. 



134 



Chapter Seven 



Fixed Tokens 



In the last chapter, we discussed the last of the tables in user 
RAM. Now we will see how and where BASIC stores its 
internal ROM-based tables. 

As we noted in Chapter 5 of Part 1 (and viewed via the 
listing program of Chapter 5 in this Part), there are four kinds 
of tokens in an Atari BASIC program: (1) statement name 
tokens, (2) operator tokens, (3) variable tokens, and (4) 
constant tokens (string and numeric constants). Also, we 
learned in Part 1 how the tokenizing process works, converting 
the user's ATASCII source code into tokens. What we didn't 
learn, though, was exactly what token replaces what BASIC 
keyword. 

In this chapter, we present a program which will list all of 
the fixed tokens (those in ROM). Actually, the program 
presents three listings, each consisting of a list of token values 
with their associated ATASCII strings. But wait a moment! 
Three listings? There are only two ROM-based tables — SNTAB 
andOPNTAB. 

Yes, but it seems that this program is also capable of listing 
the Variable Name Table. Why list it again, when we did it so 
well in Chapter 3? Because we wanted to show you how BASIC 
itself does it. In many ways, this program emulates the 
functions of the SEARCH routine at address $A462 in the 
source listing. And, yes, BASIC uses a single routine to search 
all three of these same tables. You might want to examine 
BASIC'S SEARCH routine at the same time you peruse this 
listing. 

100 REM we make use of the general purpose 

110 REM token lister three times: 

200 PRINT : PRINT "A LIST OF VARIABLE TOKENS" 

210 ADDR=PEEK(130)+256*PEEK(131) 

220 SKIP=0:TOKEN=128:GOSUB 1000 

300 PRINT : PRINT "A LIST OF STATEMENT TOKENS" 

310 ADDR=42159:SKIP=2:TOKEN=0:GOSUB 1000 

400 PRINT : PRINT "A LIST OF OPERATOR TOKENS" 

410 ADDR=42979:SKIP=0:TOKEN=16:GOSUB 1000 

420 STOP 

1000 REM a general purpose token listing routine 

135 



Chapter Seven 



1001 REM 

1002 REM On entry to this routine, the following 

1003 REM variables have meanings: 

1004 REM ADDR = address of beginning of table 

1005 REM SKIP = bytes per entry to skip 

1006 REM TOKEN = starting token number 

1007 REM 

1100 ADDR=ADDR+SKIP: IF PEEK(ADDR)=0 THEN RETURN 

1110 PRINT TOKEN, :T0KEN=T0KEN+1 

1120 IF PEEK(ADDR)>127 THEN 1140 

1130 PRINT CHR$( PEEK (ADDR) ) ; : ADDR=ADDR+1 : GOTO 1120 

1140 PRINT CHR$ ( PEEK ( ADDR )-l 28 ) : ADDR=ADDR+1 : GOTO 1100 

The main routine is actually lines 1100 through 1140 (while 
lines 1000 through 1007 simply explain it all). It's actually fairly 
simple. Each table is assumed to consist of a fixed number of 
bytes followed by a variable number of ATASCII bytes, the last 
of which has its upper bit on. 

In line 1100, we skip over the fixed bytes (if any) and check 
for the end of the table. After that, we simply print the token 
value followed by the name. 

Worth examining, though, are lines 200 through 420, 
where we call the main subroutine. First, note that the Variable 
Name Table has no bytes to skip and is located via its zero-page 
pointer. Naturally, the first variable token value is 128. 

Each entry in the Statement Name Table (SNTAB, at 
location $A4AF) has two leading bytes (actually, the two-byte 
address, minus 1, of the syntax table entry for this statement). 
Statement name token values begin at zero, and 42159 is the 
decimal address of SNTAB. 

Finally, the smallest-numbered operator token is 16 
decimal (except for string and numeric constants, which are 
special cased). There are no leading bytes in the Operator 
Name Table, and it starts at location 42979 decimal (OPNTAB, 
at$A7E3). 



136 



Chapter Eight 



What Takes 
Precedence? 



There was one other ROM-based table mentioned in Part 1 
which deserves some attention here. You may recall that when 
an expression is executed, the execution operators are given 
particular precedences, so that in BASIC, 2 + 3*4 equals 14, not 
20 . Chapter 7 of Part 1 does a particularly thorough job of 
explaining the concepts of precedence. 

The program presented in this chapter prints out all of 
BASIC'S operator tokens along with their token values and 
their dual precedence values. Actually, the program provides a 
visual readout of OPRTAB (Operator PRecedence TABle, at 
$AC3F). 

In each pair of precedence values listed, the first number is 
the go-onto-stack value and the second is the come-off-stack 
value. 

100 PRINT "A LIST OF OPERATOR TOKENS" 

110 PRINT " WITH THEIR PRECEDENCE TABLE VALUES" 

220 SKIP=0:TOKEN=128:GOSUB 1000 

1000 ADDR=42979:REM WHERE OP NAMES START 

1010 TOKEN=16:REM LOWEST TOKEN VALUE 

1020 REM NOW THE MAIN CODE LOOP 

1100 IF PEEK(ADDR)=0 THEN STOP 

1110 PRINT TOKEN, : PREC=PEEK( 44095+TOKEN-16 ) 

1120 PRINT INT(PREC/16) ; ": " ; PREC-16*INT (PREC/16 ) , 

1130 PREC=PEEK(ADDR) :ADDR=ADDR+1 

1140 IF PREC<128 THEN PRINT CHR$ ( PREC) ; : GOTO 1130 

1150 PRINT CHR$(PREC-128) :TOKEN=TOKEN+l : GOTO 1100 

If you closely examined the program in the last chapter, 
you will note a striking similarity to this program, especially 
lines 1100 through 1150. Actually, the only thing we have really 
added is the precedence printout of line 1120. 

And note the form of the PEEK in line 1110. Then look at 
the line of code at address $AAF1 in the BASIC listing. Given 



137 



Chapter Eight 



the limitations of dissimilar languages, the code is identical. 
This is more evidence that you really can use BASIC as a tool to 
diagnose itself. 



138 



Chapter Nine 



Using What 
We Know 



Now that Atari BASIC stands revealed before you, what do 
you do with it? Many authors have, even without benefit of the 
listing in this book, either used or fooled BASIC in ways that 
we who designed it never dreamed of. 

For example, consider what happens if you change 
BASIC'S STARP pointer ($8C) to be equal to its ENDSTAR 
value ($8E). Remember, BASIC'S SAVE command saves 
everything from the contents of VNTP to the contents of 
STARP (as documented in Chapter 10 of Part 1). So changing 
what is in STARP is tantamount to telling BASIC to SAVE more 
(or less) than what it normally would. Presto! We can now save 
the entire array and string space to disk or tape, also. 

Is it useful? Here's one program that is, using the concepts 
we learned in the previous chapters. 

30000 PRINT : PRINT "WHAT VARIABLE NUMBER 

DO YOU": PRINT, "WISH TO FIND 
30010 INPUT QV 

30020 QA=PEEK(130)+256*PEEK(131 ) :QN=128 
30030 IF QN=QV THEN 30060 
30040 IF PEEK ( QA )< 128 THEN QA=QA+l:GOTO 

30040 
30050 QN=QN+l:QA=QA+l:GOTO 30030 
30060 IF PEEK(QA)<128 THEN PRINT CHR$(PE 

EK(QA) ) ; :QA=QA+l:GOTO 30060 
30070 PRINT CHR$(PEEK(QA)-128) ; " IS THE 

VARIABLE" 
30100 QA=PEEK(136)+256*PEEK(137) 
30110 QN=PEEK(QA)+256*PEEK(QA+1) :QL=PEEK 

( QA+2 ) : QSV=QA : QA=QA+3 
30120 IF QN>32767 THEN PRINT " — END — ":E 

ND 
30130 QS=PEEK(QA) : QT=PEEK(QA+1 ) :QA=QA+2: 

IF QT>1 AND QT<55 THEN 30150 



139 



Chapter Nine 



30140 QA=QSV+QL : GOTO 30110 

30150 IF PEEK(QA)=QV THEN PRINT "LINE 

QN:GOTO 30140 
30160 IF PEEK(QA)>15 THEN 30200 
30170 IF PEEK (QA) =14 THEN QA=QA+6:GOTO 3 

0200 
30180 QA=QA+PEEK(QA+1)+1 
30200 QA=QA+1:IF QA<QSV+QS THEN 30150 
30210 IF QA<QSV+QL THEN 30130 
30220 GOTO 30110 

What does it do? It finds all the places in your program that 
you used a particular variable. And how do you use it? Type it 
in, LIST it to disk or cassette, and clear the user memory via 
NEW. Now type, ENTER, or LOAD the program you wish to 
investigate (and then SAVE it, if you haven't already done so). 
Finally, ENTER this program fragment from the disk or cassette 
where you LISTed it and type GOTO 30000. 

Although the program asks you for a variable number 
(which you can get via the program of Chapter 3), it doesn't 
really matter if you don't know it. The program will print your 
chosen variable's name before giving all the references. If you 
chose wrong, try again. 

And how does it work? Somewhat like the program token 
lister of Chapter 5, except that here we are simply skipping 
everything but variable name references. First, though, we use 
a modified Variable Name Table lister (lines 30020 through 
30070) to tell you what name you chose. 

Then, we start at the beginning of the program (line 30100) 
and check each user line number (30110 and 30120). Within 
each line, we loop through, checking all statements (30130), 
skipping entirely all REMs, DATA lines, and lines with syntax 
errors (line 30140). If we find ourselves in an expression, we 
check for a matching variable token reference (line 30150) and 
print it if found, after which we skip the rest of the line. We also 
skip over numeric and string constants (lines 30170 and 30180). 
Finally, we check to see if we are at the end of the statement 
(30200) or the end of a line (30210 and 30220). 

This is a fairly large program fragment, and it will prove 
most useful in very large programs, where you can't 
remember, for example, how many places you are using the 
variable name LOOP. So you might want to try to leave room 
in memory for this aid; you may be very glad you did. 

140 



Part Three 



Atari BASIC 
Source Code 



Copyright © 1978, 1979, 1983 
Optimized Systems Software 
Cupertino, CA 

Printed in the United States of America 

This program may not be reproduced, stored in a retrieval system, or transmitted in 
whole or in part, in any form, or by any means, be it electronic, mechanical, photo- 
copying, recording, or otherwise without the prior written permission of 

Optimized Systems Software, Inc. 

10379 Lansdale Avenue 

Cupertino, California 95014 (U.S.A.) 

Telephone: (408) 446-3099 
142 



Source Code 



Some Miscellaneous Equates 



0001 


PATSIZ 


EQU 


SI 


0020 


ZICB 


EQU 


520 


0080 


ZPG1 


EQU 


$80 


0480 


MISCR1 


EQU 


5480 


0500 


MISCRAM 


EQU 


5500 


E456 


CIO 


EQU 


SE456 


0340 


IOCBORG 


EQU 


5340 


0300 


DCBORG 


EQU 


5300 


A000 


ROM 


EQU 


5A000 


00D2 


ZFP 


EQU 


5D2 



EQU 



59B 



PATCH AREA SIZE 

zero PagelOCB 

beginning of BASIC'S zero page 

syntax stack, etc. 

other RAM usage 

in OS ROMs 

where IOCBs start 

where DCB (for SIO) is 

begin code here 

begin fltg point work area 

ATASCII end of line 



02E7 


LMADR 


EQU 


52E7 


02E5 


HMADR 


EQU 


52E5 


02E5 


HIMEM 


EQU 


HMADR 


D800 


FPORG 


EQU 


5D800 


0011 


BRKBYT 


EQU 


511 


0008 


WARMFL 


EQU 


$08 


D20A 


RNDLOC 


EQU 


5D20A 


BFF9 


CRTGI 


EQU 


SBFFC-3 


005D 


EPCHAR 


EQU 


55D 


E471 


BYELOC 


EQU 


5E471 


000A 


DOSLOC 


EQU 


50A 


0055 


SCRX 


EQU 


555 


0054 


SCRY 


EQU 


554 


02C4 


CREGS 


EQU 


52C4 


02FB 


SVCOLOR 


EQU 


$2FB 


D208 


SREG1 


EQU 


$D208 


D200 


SREG2 


EQU 


$D200 


D201 


SREG3 


EQU 


5D201 


D20F 


SKCTL 


EQU 


SD20F 


0270 


GRFBAS 


EQU 


5270 


02FE 


DSPFLG 


EQU 


52FE 


000E 


APHM 


EQU 


$E 



system lo mem 
system high mem 



fltg point in OS ROMs 

warmstart flag 

get a random byte here 

cartridge init vector 

the "?" for INPUT statement 

where to go for BYE 

via here to exit to DOS 

X AXIS 

Y AXIS 

COLOR REGISTER 

SAVE COLOR FOR CIO 

SOUND REG 1 

SOUND REG 2 

SOUND REG 3 

sound control 

1ST GRAPHICS FUNCTION ADDR 

ATARI DISPLAY FLAG 

APPLICATION HIGH MEM 



Zero Page 



RAM Table Pointers 



0000 


a 


0080 


ORG 




ZPG1 


0080 






LOMEM 






0080 






ARGOPS 






0080 






ARGSTK 






0080 


= 


0002 


OUTBUFF 


DS 


2 


0082 


= 


0002 


VNTP 


DS 


2 


0084 


= 


0002 


VNTD 


DS 


2 


0086 


= 


0002 


WTP 


DS 


2 


0088 






ENDWT 






0088 


= 


0002 


STMTAB 


DS 


2 


008A 


= 


0002 


STMCUR 


DS 


2 


008C 


= 


0002 


STARP 


DS 


2 


008E 






ENDSTAR 






008E 


■ 


0002 


RUNSTK 


DS 


2 


0090 






TOPRSTK 






0090 


= 


0002 


MEMTOP 


DS 


2 


0092 


K 


0001 


MEOLFLG 


DS 


1 


0093 


= 


0001 




DS 


1 



LOW MEMORY POINTER 
ARGUMENT/OPERATOR STACK 

SYNTAX OUTPUT BUFFER 
VARIABLE NAME TABLE POINTER 
VARIABLE NAME TABLE DUMMY END 
VARIABLE VALUE TABLE POINTER 
END VARIABLE VALUE TABLE 
STATEMENT TABLE [PROGRAM] ; 
POINTER 

CURRENT PGM PTR 
STRING/ARRAY TABLE POINTER 
END STRING/ARRAY SPACE 
RUN TIME STACK 
END RUN TIME STACK 
TOP OF USED MEMORY 
MODIFIED EOL FLAG 
: : SPARE: : 



143 



Source Code 



Miscellaneous Zero Page RAM 



0094 




0001 


COX 


DS 


1 


0095 






POKADR 






0095 


= 


0002 


SRCADR 


DS 


2 


0097 






INDEX2 






0097 


= 


0002 


SVESA 


DS 


2 


0099 


= 


0002 


MVFA 


DS 


2 


009B 


= 


0002 


MVTA 


DS 


2 


009D 






CPC 






009D 


= 


0002 


WWTPT 


DS 


2 


009F 






MAXCIX 






009P 


= 


0001 


LLNGTH 


DS 


1 


00A0 


- 


0002 


TSLNUM 


DS 


2 


00A2 


= 


0002 


MVLNG 


DS 


2 


00A4 


= 


0002 


ECSIZE 


DS 


2 


00A6 


= 


0001 


DIRFLG 


DS 


1 


00A7 






STMLBD 






00A7 


= 


0001 


NXTSTD 


DS 


1 


00A8 






STMSTRT 






00A8 


= 


0001 


STINDEX 


DS 


1 


00A9 






STKLVL 






00A9 






IBUFFX 






00A9 


= 


0001 


OPSTKX 


DS 


1 


00AA 






ARS LVL 






00AA 






SRCSKP 






00AA 


= 


0001 


ARSTKX 


DS 


1 


00AB 






TSCOX 






00AB 


= 


0001 


EXSVOP 


DS 


1 


00AC 






TVSCIX 






00AC 


m 


0001 


EXSVPR 


DS 


1 


00AD 






SWNTP 






00AD 


= 


0002 


LELNUM 


DS 


2 


00AF 






ATEMP 






00AF 






STENUM 






00AF 


= 


0001 


SCANT 


DS 


1 


00B0 






SVONTC 






00B0 


= 


0001 


COMCNT 


DS 


1 


00B1 






SVWTE 






00B1 


= 


0001 


ADFLAG 


DS 


1 


00B2 






SVONTL 






00B2 


= 


0001 


SVDISP 


DS 


1 


00B3 






ONLOOP 






00B3 






SVONTX 






00B3 


= 


0001 


SAVDEX 


DS 


1 


00B4 


= 


0001 


ENTDTD 


DS 


1 


00B5 


= 


0001 


LISTDTD 


DS 


1 


00B6 


= 


0001 


DATAD 


DS 


1 


00B7 


= 


0002 


DATALN 


DS 


2 


00B9 


= 


0001 


ERRNUM 


DS 


1 


00BA 


= 


0002 


STOPLN 


DS 


2 


00BC 


B 


0002 


TRAPLN 


DS 


2 


00BE 


= 


0002 


SAVCUR 


DS 


2 


00C0 


= 


0001 


IOCMD 


DS 


1 


00C1 


= 


0001 


IODVC 


DS 


1 


00C2 


= 


0001 


PROMPT 


DS 


1 


00C3 


- 


0001 


ERRSAV 


DS 


1 


00C4 


= 


0002 


TEMPA 


DS 


2 


00C6 


=! 


0002 


ZTEMP2 


DS 


2 


00C8 


= 


0001 


COLOR 


DS 


1 


00C9 


= 


0001 


PTABW 


DS 


1 


00CA 


= 


0001 


LOADFLG 


DS 


1 



USED FOR FREQUENTLY USED VALUES 
TO DECREASE ROM SIZE AND INCREASE 
EXECUTION SPEED. ALSO USED FOR VARIOUS 
INDIRECT ADDRESS POINTERS. 



CURRENT OUTPUT INDEX 

POKE ADDRESS 

SEARCH ADR 

ARRAY INDEX 2 

SAVE EXPAND START ADR 

MOVE FROM ADR 

MOVE TO ADR 

CUR SYNTAX PGM COUNTER 

WORKING VAR TABLE PTR VALUE 

MAX SYNTAX CIX 

LINE LENGTH 

TEST LINE NO 

MOVE LENGTH 

MOVE SIZE 

DIRECT EXECUTE FLAG 

STMT LENGTH BYTE DISPL 

NEXT STMT DISPL 

STMT START CIX 

CURR STMT INDEX 

SYNTAX STACK LEVEL 

INPUT BUFFER INDEX 

OPERATOR STACK INDEX 

SEARCH SKIP FACTOR 

ARG STACK INDEX 

TSCOW LENGTH BYTE PTR 

SAVED OPERATOR 

SAVE CIX FOR TVAT 

SAVED OPERATOR PRECEDENCE 

SAVE VAR NAME TBL PTR 

LIST END LINE I 

TEMP FOR ARRAYS 

SEARCH TABLE ENTRY NUMBER 

LIST SCAN COUNTER 

SAVE ONT SRC CODE 

COMMA COUNT FOR EXEXOR 

SAVE VAR VALUE EXP SIZE 

ASSIGN/DIM FLAG 

SAVE ONT SRC ARG LEN 

DISPL INTO LINE OF FOR/GOSUB 

TOKEN 

LOOP CONTROL FOR OP 

SAVE ONT SRC INDEX 

SAVE INDEX INTO STMT 

ENTER DEVICE TB 

LIST DEVICE TBL 

DATA DISPL 

DATA LINNO 

ERROR # 

LINE # STOPPED AR [FOR CON] 

TRAP LINE # [FOR ERROR] 

SAVE CURRENT LINE ADDR 

I/O COMMAND 

I/O DEVICE 

PROMPT CHAR 

ERROR # FOR USER 

TEMP ADDR CELL 

TEMP 

SET COLOR FOR BASE 

PRINT TAB WIDTH 

LOAD IN PROGRESS FLAG 



144 



Source Code 



Argument Work Area (AWA) 



Floating Point Work Area 



00CB 


= 


00D2 


ORG 




ZFP 






00D2 






TVTYPE 






; VARIABLE TYPE 


00D2 


m 


0001 


VTYPE 


DS 


1 


; VARIABLE TYPE 


00D3 






TVNUM 






; VARIABLE NUMBER 


00D3 


= 


0001 


VNUM 


DS 


1 


J VARIABLE NUMBER 




= 


0006 


FPREC 


EQU 


6 








= 


0005 


FMPREC 


EQU 


FPREC-1 


; LENGTH OF FLOATING POINT 
; MANTISSA 


00D4 






BININT 






; FP 


REGO 


00D4 


= 


0001 


FR0 


DS 


1 


; FP 


REG0 


00D5 


= 


0005 


FR0M 


DS 


FPREC-1 


; FP 


REG0 MANTISSA 


00DA 


= 


0006 


FRE 


DS 


FPREC 


I FP 


REG0 EXP 


00E0 


= 


0001 


FR1 


DS 


1 


; FP 


REG 1 


00E1 


= 


0005 


FR1M 


DS 


FPREC-1 


; FP 


REG1 MANTISSA 


00E6 


= 


0006 


FR2 


DS 


FPREC 


| FP 


REG 2 


00EC 


= 


0001 


FRX 


DS 


1 


; FP 


SPARE 



RAM for ASCII to Floating Point Conversion 



00ED 


= 0001 


EEXP 


DS 


1 


00EE 




FRSIGN 






00EE 


= 0001 


NSIGN 


DS 


1 


00EF 




SQRCNT 






00EF 




PLYCNT 






00EF 


= 0001 


ESIGN 


DS 


1 


00F0 




SGNFLG 






00F0 


= 0001 


FCHRFLG 


DS 


1 


00F1 




XFMFLG 






00F1 


= 0001 


DIGRT 


DS 


1 



Input Buffer Controls 

00F2 = 0001 
00F3 = 0002 

Temps 

00F5 = 0002 
00F7 = 0002 
00F9 = 0002 

Miscellany 



CIX 


DS 


1 


INBUFF 


DS 


2 


ZTEMP1 


DS 


2 


ZTEMP4 


DS 


2 


ZTEMP3 


DS 


2 



00FB 




DEGFLG 






00FB 


= 0001 


RADFLG 


DS 


1 




= 0000 


RADON 


EQU 






= 0006 


DEGON 


EQU 




00FC 


= 0002 


FLPTR 


DS 


2 


00FE 


= 0002 


FPTR2 


DS 


2 



VALUE OF E 
FP SIGN 
SIGN OF t 



SIGN OF EXPONENT 

1ST CHAR FLAG 

# OF DIGITS RIGHT OF DECIMAL 



CURRENT INPUT INDEX 
LINE INPUT BUFFER 



LOW LEVEL ZERO PageTEMPS 



0=RADIANS, 6= DEGREES 
INDICATE RADIANS 
INDICATES DEGREES 
POLYNOMIAL POINTERS 



Miscellaneous Non-Zero Page RAM 

; USED FOR VALUES NOT ACCESSED FREQUENTLY 



0100 


= 


0480 


ORG 




MISCR1 








= 


0480 


STACK 


EQU 


* 


; SYNTAX STACK 




0480 


= 


0001 


SIX 


DS 


1 


; INPUT INDEX 




0481 


= 


0001 


SOX 


DS 


1 


,- OUTPUT INDEX 




0482 


= 


0002 


SPC 


DS 


2 


; PGM COUNTER 




0484 


= 


057E 


ORG 




STACK+254 






057E 


m 


0001 


LBPR1 


DS 


1 


; LBUFF PREFIX 


1 


057F 


=s 


0001 


LBPR2 


DS 


1 


; BLUFF PREFIX 


2 


0580 


= 


0080 


LBUFF 


DS 


128 


; LINE BUFFER 





145 



Source Code 



0600 


= 05E0 


ORG 




LBUFF+$60 


05E0 


= 0006 


PLYARG 


DS 


FPREC 


05E6 


= 0006 


PPSCR 


DS 


FPREC 


05EC 


= 0006 


FPSCR1 


DS 


FPREC 




= 05E6 


FSCR 


EQU 


FPSCR 




= 05EC 


FSCR1 


EQU 


FPSCR1 


lOCBArea 








05F2 


= 0340 


ORG 




IOCBORG 



IOCB — I/O Control Block 



THERE ARE 8 1/0 CONTROL BLOCKS 
1 IOCB IS REQUIRED FOR EACH 
CURRENTLY OPEN DEVICE OR FILE. 



0340 






IOCB 








0340 


= 


0001 


ICHID 


DS 


1 ; 


DEVICE HANDLER ID 


0341 


= 


0001 


ICDNO 


DS 


1 ; 


DEVICE NUMBER 


0342 


= 


0001 


ICCOM 


DS 


1 ; 


I/O COMMAND 


0343 


= 


0001 


ICSTA 


DS 


1 


I/O STATUS 


0344 


= 


0001 


ICBAL 


DS 


1 




0345 


s= 


0001 


ICBAH 


DS 


1 


BUFFER ADR [H,L] 


0346 


= 


0002 


ICPUT 


DS 


2 ; 


PUT A BYTE VIA THIS 


0348 


= 


0001 


ICBLL 


DS 


1 




0349 


o 


0001 


ICBLH 


DS 


1 ; 


BUFFER LENGTH [H,L] 


034A 


= 


0001 


ICAUX1 


DS 


1 


AUXILIARY 1 


034B 


= 


0001 


ICAUX2 


DS 


1 


AUXILIARY 2 


034C 


= 


0001 


ICAUX3 


DS 


1 


AUXILIARY 3 


034D 


■ 


0001 


ICAUX4 


DS 


1 ,- 


AUXILIARY 4 


034E 


= 


0001 


ICAUX5 


DS 


1 


AUXILIARY 5 


034F 


= 


0001 


DS 


1 




SPARE 




= 


0010 


ICLEN 


EQU 


*-IOCB 




0350 


= 


0070 


DS 


ICLEN*7 


SPACE FOR 7 MORE IOCBS 


ICCOM Value Equates 










= 


0001 


ICOIN 


EQU 


$01 


OPEN INPUT 




= 


0002 


ICOOUT 


EQU 


$02 


OPEN OUTPUT 




= 


0003 


ICOIO 


EQU 


$03 


OPEN UN/OUT 




= 


0004 


ICGBR 


EQU 


$04 


GET BINARY RECORD 




= 


0005 


ICGTR 


EQU 


$05 


GET TEXT RECORDS 




= 


0006 


ICGBC 


EQU 


$06 


GET BINARY CHAR 




= 


0007 


ICGTC 


EQU 


$07 


GET TEXT CHAR 




= 


0008 


ICPBR 


EQU 


?08 


PUT BINARY RECORD 




= 


0009 


ICPTR 


EQU 


$09 


PUT TEXT RECORD 




= 


000A 


ICPBC 


EQU 


$0A 


PUT BINARY CHAR 




= 


000B 


ICPTC 


EQU 


$0B 


PUT TEXT CHAR 




= 


000C 


ICCLOSE 


EQU 


$0C 


CLOSE FILE 




= 


000D 


ICSTAT 


EQU 


$0D 


GET STATUS 




= 


000E 


ICDDC 


EQU 


$0E 


DEVICE DEPENDENT 




= 


000E 


ICMAX 


EQU 


$0E 


MAX VALUE 




8 


00FF 


ICFREE 


EQU 


$FF 


IOCB FREE INDICATOR 




= 


001C 


ICGR 


EQU 


$1C 


OPEN GRAPHICS 




= 


0011 


ICDRAW 


EQU 


$11 


DRAW TO 


ICSTA 


Value Equates 














0001 


ICSOK 


EQU 


$01 


; STATUS GOOD, NO ERRORS 






0002 


ICSTR 


EQU 


$02 


; TRUNCATED RECORD 






0003 


ICSEOF 


EQU 


$03 


; END OF FILE 






0080 


ICSBRK 


EQU 


$80 


; BREAK KEY ABORT 






0081 


ICSDNR 


EQU 


$81 


; DEVICE NOT READY 






0082 


ICSNED 


EQU 


$82 


; NON-EXISTENT DEVICE 






0083 


ICSDER 


EQU 


$83 


; DATA ERROR 






0084 


ICSIVC 


EQU 


$84 


; INVALID COMMAND 






0085 


ICSNOP 


EQU 


$85 


; DEVICE/FILE NOT OPEN 






0086 


ICSIVN 


EQU 


$86 


; INVALID IOCB NUMBER 






0087 


ICSWPE 


EQU 


$87 


,- WRITE PROTECTION 



146 



Source Code 



Equates for Variables 



0000 

0080 
0040 
0002 
0001 
0000 



= 0002 

= 0002 
= 0004 
= 0006 

= 0002 
= 0004 
= 0006 



= 0004 
» 000C 
= 0003 
= 0001 
= 0000 
= 0006 
= 0000 







-IN 






-ON 


EVTYPE 


EQU 





EVSTR 


EQU 


$80 


EVARRAY 


EQU 


$40 


EVSDTA 


EQU 


$02 


EVDIM 


EQU 


$01 


EVSCALER EQU 


$00 


EVNUM 


EQU 


1 


EWALUE 


EQU 


2 


EVSADR 


EQU 


2 


EVSLEN 


EQU 


4 


EVSDIM 


EQU 


6 


EVAADR 


EQU 


2 


EVAD1 


EQU 


4 


EVAD2 


EQU 


6 


jn Stack 






GFHEAD 


EQU 


4 


PBODY 


EQU 


12 


GFDISP 


EQU 


3 


GFLNO 


EQU 


1 


GFTYPE 


EQU 





FSTEP 


EQU 


6 


FLIM 


EQU 






-IN VARIABLE VALUE TABLE 
-ON ARGUMENT STACK 



VALUE TYPE CODE 

- STRING 

- ARRAY 

- ON IF EVSADR IS ABS ADR 
ON IF HAS BEEN DIM 

- SCALER 

VARIABLE NUMBER [83 - FF] 

SCALAR VALUE [6 BYTES] 

STRING DISPL [2] 
STRING LENGTH [2] 
STRING DIM [2] 

ARRAY DISPL [2] 
ARRAY DIM 1 [2] 
ARRAY DIM 2 [2] 



LENGTH OF HEADER FOR FOR/GOSUB 
LENGTH OF BODY OF FOR ELEMENT 
DISP TO SAVED LINE DISP 
DISPL TO LINE # IN HEADER 
DISPL TO TYPE IN HEADER 
DISPL TO STEP IN FOR ELEMENT 
DISPL TO LIMIT IN FOR ELEMENT 



Cold 


Start 


A000 




A000 


A5CA 


A002 


D004 * 


A004 


A508 


A006 


D045 * 


A008 




A008 


A2FF 


A00A 


9A 


A00B 


D8 


A00C 




A00C 


AEE702 


A00F 


ACE802 


A012 


8680 


A014 


8481 


A016 


A900 


A018 


8592 


A01A 


85CA 


A01C 


C8 


A01D 


8A 


A01E 


A282 


A020 


9500 


A022 


E8 


A023 


9400 


A02 5 


E8 


A026 


E092 


A028 


90F6 * 







ROM Start 




COLD START - REINIT 






WIPES 


COLDSTART 




LDA 




LOADFLG 


BNE 




COLD1 


LDA 




WARMFLG 


BNE 




WARMSTART 


COLD1 






LDX 




#$FF 


TXS 






CLD 






XNEW 






LDX 




LMADR 


LDY 




LMADR+1 


STX 




LOMEM 


STY 




LOMEM+1 


LDA 




#0 


STA 




MEOLFLG 


STA 




LOADFLG 


I NY 






TXA 






LDX 




#VNTP 


:CS1 


STA 


0,X 


INX 






STY 




0,X 


INX 






CPX 




#MEMTOP+2 


BCC 




:CS1 



IALIZES ALL MEMORY 

OUT ANY EXISTING PROGRAM 

;Y IN MIDDLE OF LOAD 
;DO COLDSTART 
; IF WARM START 
; THEN BRANCH 

| SET ENTRY STACK 

; TO TOS 

I CLEAR DECIMAL MODE 

;LOAD LOW 
;MEM VALUE 
; SET LOMEM 

; RESET MODIFIED 

; EOL FLAG 

; RESET LOAD FLAG 

; ALLOW 2 56 FOR OUTBUFF 

;VNTP 

; GET ZPG DISPC TO VNTP 
; SET TABLE ADR LOW 

; SET TABLE ADR HIGH 

; AT LIMIT 
I BR IF NOT 



A02A A286 



EXPAND VNT BY ONE 



147 



Source Code 



A02C 


A001 


LDY 


#1 




; FOR END OF VNT 


A02E 


207FA8 


JSR 


EXPLOW 




; ZERO BYTE 


A031 


A28C 


LDX 


tSTARP 




; EXPAND STMT TBL 


A033 


A003 


LDY 


#3 




| BY 3 BYTES 


A035 


207FA8 


JSR 


EXPLOW 




; GO DO IT 


A038 


A900 


LDA 


#0 




; SET 


A03A 


A8 


TAY 








A03B 


9184 


STA 


[VNTD],Y 




,- INTO WTP 


A03D 


918A 


STA 


[STMCUR] 


Y 


; INTO STMCUR+0 


A03F 


C8 


INY 








A040 


A980 


LDA 


#$80 




I $80 INTO 


A042 


91 8A 


STA 


[STMCUR] 


Y 


; STMCUR+1 


A044 


C8 


INY 








A045 


A903 


LDA 


#$03 




; $03 INTO 


A047 


91 8A 


STA 


[STMCUR] 


Y 


; STMCUR+2 


A049 


A90A 


LDA 


#10 




; SET PRINT TAB 


A04B 


85C9 


STA 


PTABW 




; WIDTH TO 10 


Warm Start 














1 WARMSTART - BASIC 


RESTART 






[ 


DOES 


NOT DESTROY CURRENT PGM 


A04D 




WARMSTART 








A04D 


20F8B8 


JSR 


RUNINIT 




; INIT FOR RUN 


A050 


2041BD 


SNX1JSR 


CLSALL 




; GO CLOSE DEVICE 1-7 


A053 


2072BD 


SNX2JSR 


SETDZ 




; SET E/L DEVICE 


A056 


A592 


LDA 


MEOLFLG 




; IF AN EOL INSERTED 


A058 


F003 "A05D 


BEQ 


SNX3 






A05A 


2099BD 


JSR 


RSTSEOL 




; THEN UN-INSERT IT 


A05D 


2057BD 


SNX3 JSR 


PREADY 


; PRINT READY MESSAGE 



Syntax 

A060 LOCAL 

Editor — Get Lines of Input 



A060 


A5CA 


A062 


D09C "A000 


A064 


A2FF 


A066 


9A 


A067 


2051DA 


A06A 


A95D 


A06C 


85C2 


A06E 


2092BA 


A071 


20F4A9 


A074 


D0EA "A060 


A076 


A900 


A078 


85F2 


A07A 


859F 


A07C 


8594 


A07E 


85A6 


A080 


85B3 


A082 


85B0 


A084 


85B1 


A086 


A584 


A088 


85AD 


A08A 


A585 


A08C 


85AE 


A08E 


20A1DB 


A091 


209FA1 


A094 


20C8A2 


A097 


A5D5 


A099 


1002 "A09D 


A09B 


85Ab 



SYNTAX 




LDA 


LOADFLG 


BNE 


COLDSTART 


LDX 


#$FF 


TXS 




JSR 


INTLBF 


LDA 


#EPCHAR 


STA 


PROMPT 


JSR 


GLGO 


JSR 


TSTBRK 


BNE 


SYNTAX 


LDA 


#0 


STA 


CIX 


STA 


MAXCIX 


STA 


COX 


STA 


DIRFLG 


STA 


SVONTX 


STA 


SVONTC 


STA 


SVWTE 


LDA 


VNTD 


STA 


SWNTP 


LDA 


VNTD+1 


STA 


SWNTP+1 


JSR 


SKBLANK 


JSR 


:GETLNUM 


JSR 


iSETCODE 


LDA 


BININT+1 


BPL 


:SYN0 


STA 


DiRFLG 



IF LOAD IN PROGRESS 
GO DO COLDSTART 
RESTORE STACK 

GO INT LBUFF 



; TEST BREAK 
; BR IF BREAK 

; INIT CURRENT 

; INPUT INDEX TO ZERO 

I OUTPUT INDEX TO ZERO 

;SET DIRECT SMT 

; SET SAVE ONT CIX 

J VALUE IN CASE 
; OF SYNTAX ERROR 



SKIP BLANKS 

CONVERT AND PUT IN BUFFER 
SET DUMMY FOR LINE LENGTH 



148 



Source Code 



A09D 




:SYN0 








A09D 


20A1DB 


JSR 


SKBLANKS 




SKIP BLANKS 


A0A0 


A4F2 


LDY 


CIX 




GET INDEX 


A0A2 


84A8 


STY 


STMSTRT 




SAVE INCASE OF SYNTAX ERROR 


A0A4 


B1F3 


LDA 


[INBUFF], 


Y 


GET NEXT CHAR 


A0A6 


C99B 


CMP 


#CR 




IS IT CR 


A0A8 


D007 "A0B1 


BNE 


:SYN1 




BR NOT CR 


A0AA 


24A6 


BIT 


DIRFLG 




IF NO LINE NO. 


ABAC 


30B2 "A060 


BMI 


SYNTAX 




THEN NO. DELETE 


A0AE 


4C89A1 


JMP 


:SDEL 




GO DELETE STMT 


A0B1 




:SYN1 








A0B1 




:XIF 








A0B1 


A594 


LDA 


COX 




SAVE COX 


A0B3 


85A7 


STA 


STMLBD 




AS PM TO STMT LENTGH BYTE 


ABB 5 


20C8A2 


JSR 


:SETCODE 




DUMMY FOR STMT LENGTH 


A0B8 


20A1DB 


JSR 


SKBLANK 




GO SKIP BLANKS 


A0BB 


A9A4 


LDA 


#SNTAB/256 


SET UP FOR STMT 


A0BD 


A0AF 


LDY 


#SNTAB&255 


NAME SEARCH 


A0BF 


A202 


LDX 


#2 






A0C1 


2062A4 


JSR 


SEARCH 




AND DO IT 


A0C4 


86F2 


STX 


CIX 






A0C6 


A5AF 


LDA 


STENUM 




GET STMT NUMBER 


A0C8 


20C8A2 


JSR 


:SETCODE 




GO SET CODE 


A0CB 


20A1DB 


JSR 


SKBLANK 






A0CE 


20C3A1 


JSR 


: SYNENT 




•AND GO SYNTAX HIM 


A0D1 


9035 "A108 


BCC 


:SYNOK 




•BR IF OK SYNTAX 
■ELSE SYNTAX ERROR 


A0D3 


A49F 


LDY 


MAXCIX 




• GET MAXCIX 


A0D5 


B1F3 


LDA 


[INBUFF] 


Y 


• LOAD MAXCIX CHAR 


A0D7 


C99B 


CMP 


#CR 




■ WAS IT CR 


A0D9 


D006 "A0E1 


BNE 


:SYN3A 




BR IF NOT CR 


A0DB 


C8 


INY 






■ MOVE CR RIGHT ONE 


A0DC 


91F3 


STA 


[INBUFF] 


Y 




A0DE 


88 


DEY 






■ THEN PUT A 


A0DP 


A920 


LDA 


#$20 




BLANK IN IT'S PLACE 


A0E1 


0980 


:SYN3A 


ORA #$80 




SET MAXCIX CHAR 


A0E3 


91F3 


STA 


[INBUFF] 


Y 


• TO FLASH 


A0E5 


A940 


LDA 


#$40 




• INDICATE SYNTAX ERROR 


A0E7 


05A6 


ORA 


DIRFLG 






A0E9 


85A6 


STA 


DIRFLG 




- IN DIRFLG 


A0EB 


A4A8 


LDY 


STMSTRT 




■RESTORE STMT START 


A0ED 


84F2 


STY 


CIX 






A0EF 


A203 


LDX 


#3 




-SET FOR FIRST STMT 


A0F1 


86A7 


STX 


STMLBD 






A0F3 


E8 


INX 






■ INC TO CODE 


A0F4 


8694 


STX 


COX 




•AND SET COX 


A0F6 


A937 


LDA 


#CERR 




■ GARBAGE CODE 


A0F8 


20C8A2 


:SYN3 


JSR :SETCODE 


■GO SET CODE 


A0FB 




: XDATA 








A0FB 


A4F2 


LDY 


CIX 




•GET INDEX 


A0FD 


B1F3 


LDA 


[INBUFF] 


Y 


•GET INDEX CHAR 


A0FF 


E6F2 


INC 


CIX 




• I NC TO NXT 


A101 


C99B 


CMP 


#CR 




■IS IT CR 


A103 


D0F3 "A0F8 


BNE 


:SYN3 




•BR IF NOT 


A105 


20C8A2 


JSR 


:SETCODE 






A108 


A594 


:SYNOK 


LDA COX 




• GET DISPL TO END OF STMT 


A10A 


A4A7 


LDY 


STMLBD 






A10C 


9180 


STA 


[OUTBUFF], Y 


;SET LENGTH BYTE 


A10E 


A4F2 


LDY 


CIX 




■GET INPUT DISPL 


A110 


88 


DEY 








Alll 


B1F3 


LDA 


[INBUFF] 


Y 


•GET LAST CHAR 


A113 


C99B 


CMP 


#CR 




-IS IT CR 


A115 


D09A "A0B1 


BNE 


:SYN1 




•BR IF NOT 


A117 


A002 


:SYN4 


LDY #2 




• SET LINE LENGTH 


A119 


A594 


LDA 


COX 




• INTO STMT 



149 



Source Code 



A11B 9180 



[OUTBUFF],Y 



A11D 20A2A9 

A120 A900 

A122 B003 "A127 



:SYN5 JSR GE 
LDA #0 
BCS :SYN6 



;GO GET STMT 



A124 




SYN5A 






A124 


20DDA9 


JSR 




GETLL 


A127 


38 : 


SYN6 


SEC 




A128 


E594 


SBC 




COX 


A12A 


F020 "A14C 


BEQ 




:SYNIN 


A12C 


B013 "A141 


BCS 




: SYNCON 


A12E 


49FF 


EOR 




#?FF 


A130 


A8 


TAY 






A131 


C8 


I NY 






A132 


A28A 


LDX 




JSTMCUR 


A134 


207FA8 


JSR 




EXPLOW 


A137 


A597 


LDA 




SVESA 


A139 


858A 


STA 




STMCUR 


A13B 


A598 


LDA 




SVESA+1 


A13D 


858B 


STA 




STMCURU 


A13F 


D00B "A14C 


BNE 




:SYNIN 


A141 


48 


SYNCON 


PHA 


; CONTPJ 


A142 


20D0A9 


JSR 




GNXTL 


A145 


68 


PLA 






A146 


A8 


TAY 






A147 


A28A 


LDX 




#STMCUR 


A149 


20FBA8 


JSR 




CONTLOW 


A14C 


A494 


SYNIN 


LDY 


COX 


A14E 


88 


SYN7 


DEY 




A14F 


B180 


LDA 




[OUTBUFF],Y 


A151 


918A 


STA 




[STMCUR], Y 


A153 


98 


TYA 






A154 


D0F8 "A14E 


BNE 




:SYN7 


A156 


24A6 


BIT 




DIRFLG 


A158 


502A ~A184 


BVC 




:SYN8 


A15A 


A5B1 


LDA 




SWVTE 


A15C 




ASLfl 






A15C 


+0A 


ASL 




A 


A15D 




ASL? 






A15D 


+0A 


ASL 




A 


A15E 




ASL? 






A15E 


+0A 


ASL 




A 


A15F 


A8 


TAY 






A160 


A288 


LDX 




IENDWT 


A162 


20FBA8 


JSR 




CONTLOW 


A165 


38 


SEC 






A166 


A584 


LDA 




VNTD 


A168 


E5AD 


SBC 




SWNTP 


A16A 


A8 


TAY 






A16B 


A585 


LDA 




VNTD+1 


A16D 


E5AE 


SBC 




SWNTP + 1 


A16F 


A284 


LDX 




#VNTD 


A171 


20FDA8 


JSR 




CONTRACT 


A174 


24A6 


BIT 




DIRFLG 


A176 


1006 "A17E 


BPL 




:SYN9A 


A178 


2078B5 


JSR 




LDLINE 


A17B 


4C60A0 


JMP 




SYNTAX 


A17E 


205CB5 


SYH9A 


JSR 


LLINE 


A181 


4C60A0 


SYN9 


JMP 


SYNTAX 


A184 


10FB *A181 


SYN8 


BPL 


:SYN9 


A186 


4C5FA9 


JMP 




EXECNL 


A189 


20A2A9 


SDEL 


JSR 


GETSTMT 


A18C 


B0F3 "A181 


BCS 




:SYN9 


A18E 


20DDA9 


JSR 




GETLL 


A191 


48 


PHA 







;GO GET LINE LENGTH 

ACU=LENGTH[ OLD-NEW] 

BR NEW=OLD 
BR OLD>NEW 
OLD<NEW 
COMPLEMENT RESULT 



POINT TO STMT CURRENT 
GO EXPAND 
RESET STMCUR 



; POINT TO STMT CURRENT 
;GO CONTRACT 

STMT LENGTH 

MINUS ONE 

GET BUFF CHAR 
PUT INTO STMT TBL 

TEST END 

BR IF NOT 
TEST FOR SYNTAX ERROR 
BR IF NOT 

CONTRACT WT 



; CONTRACT VNT 



IF STMT NOT DIRECT 
THE BRANCH 

ELSE LIST DIRECT LINE 
THEN BACK TO SYNTAX 
LIST ENTIRE LINE 



; GO TO PROGRAM EXECUTOR 

; GO GET LINE 
; BR NOT FOUND 
;GO GET LINE LENGTH 
; Y 



150 



Source Code 



A192 


20D0A9 


A195 


68 


A196 


A8 


A197 


A28A 


A199 


20FBA8 


A19C 


4C60A0 



JSR 


GNXTL 




PLA 






TAY 






LDX 


SSTMCUR 


;GET STMCUR DISPL 


JSR 


CONTLOW 


,- GO DELETE 


JMP 


SYNTAX 


;GO FOR NEXT LINE 



Get a Line Number 



A19F 

A19F 2000D8 
A1A2 9008 "A1AC 
A1A4 



GETLNUM-GET A LINE NO FROM ASCLT IN INBUFF 

TO BINARY INTO OUTBUFF 

GETLNUM 

JSR CVAFP ; GO CONVERT LINE # 

BCC :GLNUM ; BR IF GOOD LINE # 

GLN1 



A1A4 A900 LDA #0 

A1A6 85F2 STA CIX 

A1A8 A080 LDY #$80 

A1AA 3009 "A1B5 BMI :SLNUM 



SET LINE 
=$8000 



A1AC 


2056AD 


:GLNUM 


A1AF 


A4D5 


LDY 


A1B1 


30F1 "A1A4 


BMI 


A1B3 


A5D4 


LDA 


A1B5 




:SLNUM 


A1B5 


84A1 


STY 


A1B7 


85A0 


STA 


A1B9 


20C8A2 


JSR 


A1BC 


A5A1 


LDA 


A1BE 


85D5 


STA 


A1C0 


4CC8A2 


JMP 


SYNENT 




A1C3 




: SYNENT 


A1C3 


A001 


LDY 


A1C5 


B195 


LDA 


A1C7 


859E 


STA 


A1C9 


8D8304 


STA 


A1CC 


88 


DEY 


A1CD 


B195 


LDA 


A1CF 


859D 


STA 


A1D1 


8D8204 


STA 


A1D4 


A900 


LDA 


A1D6 


85A9 


STA 


A1D8 


A594 


LDA 


A1DA 


8D8104 


STA 


A1DD 


A5F2 


LDA 


A1DF 


8D8004 


STA 



JSR CVFPI 
BININT+1 
:GLN1 
BININT 



TSLNUM+1 

TSLNUM 

:SETCODE 

TSLNUM+1 

BININT+1 

:SETCODE 



CONVERT FP TO IE 

LOAD RESULT 

BR IF LNO>32767 



SET LINE # 
AND LOW 
OUTPUT LOW 
OUTPUT HI 



; AND RETURN 



PERFORM LINE PRE-COMPILE 



#1 

[SRCADR], Y 
CPC+1 
SPC + 1 

[SRCADR], Y 

CPC 

SPC 

#0 

STKLVL 

COX 

SOX 

CIX 

SIX 



; GET PC HIGH 
;SET PGM COUNTERS 



SET STKLUL 

SET STKLUL 

MOVE 

COX TO SOX 

MOVE 

CIX TO SIX 



NEXT 

A1E2 
A1E5 



= A1E2 
20A1A2 



301A "A201 



GET NEXT SYNTAX CODE 
AS LONG AS NOT FAILING 



NEXT EQU * 
JSR :NXSC 



GET NEXT CODE 

BR IF REL-NON-TERMINAL 



A1E7 


C901 


CMP 




#1 


A1E9 


902A "A215 


BCC 




:GETADR 


A1EB 


D008 ~A1F5 


BNE 




rTSTSUC 


A1ED 


2015A2 


JSR 




:GETADR 


A1F0 


90F0 ~A1E2 


BCC 




:NEXT 


A1F2 


4C6CA2 


JMP 




:FAIL 


A1F5 


C905 


:TSTSUC 


CMP 


#5 



; TEST CODE=l 

; BR CODE=0 [ABS-NON-TERMINAL] 

; BR CODE >1 

,- CODE=l [EXTERNAL SUBROUTINE] 

■ BR IF SUB REPORTS SUCCESS 

; ELSE GO TO FAIL CODE 

; TEST CODE = 5 



151 



Source Code 



A1F7 


9059 "A252 


BCC 


:POP 


A1F9 


20A9A2 


JSR 


:TERMTST 


MFC 


90E4 ~A1E2 


BCC 


:NEXT 


A1FE 


4C6CA2 


JMP 


:FAIL 


A201 


38 


:ERNTV SEC 




A202 


A200 


LDX 


#0 


A204 


E9C1 


SBC 


#$C1 


A206 


B002 "A20A 


BCS 


:ERN1 


A208 


A2FF 


LDX 


#?FF 


A20A 


18 


:ERN1 CLC 




A20B 


659D 


ADC 


CPC 


A20D 


48 


PHA 




A20E 


8A 


TXA 




A20F 


659E 


ADC 


CPC+1 


A211 


48 


PHA 




A212 


4C28A2 


JMP 


:PUSH 




= A215 


:GETADR EQU 


* 


A215 


20A1A2 


JSR 


:NXSC 


A218 


48 


PHA 




A219 


20A1A2 


JSR 


:NXSC 


A21C 


48 


PHA 




A21D 


9009 ~A228 


BCC 


:PUSH 


A21F 


68 


PLA 




A220 


A8 


TAY 




A221 


68 


PLA 




A222 


AA 


TAX 




A223 


98 


TYA 




A224 


48 


PHA 




A225 


8A 


TXA 




A226 


48 


PHA 




A227 


60 


RTS 





CODE = [2, 3, OR 4] POP UP TO 

NEXT SYNTAX CODE 

CODE>5 GO TEST TERMINAL 

BR IF SUCCESS 

ELSE GO TO FAIL CODE 

RELATIVE NON TERMINAL 
TOKEN MINUS 

BR IF RESULT PLUS 
ADD A MINUS 

RESULT PLUS CPC 
IS NEW CPC-1 



SAVE NEW PC HIGH 

GO PUSH 

GET DOUBLE BYTE ADR [-1] 

GET NEXT CODE 

SAVE ON STACK 

GET NEXT CODE 

SAVE ON STACK 

BR IF CODE =0 

EXCHANGE TOP 

2 ENTRIES ON 

CPU STACK 



ELSE GOTO EXTERNAL SRT VIA RTS 



PUSH 



PUSH TO NEXT STACK LEVEL 





= A228 


:PUSH EQU 


* 


A228 


A6A9 


LDX 


STKLVL 


A22A 


E8 


I NX 




A22B 


E8 


I NX 




A22C 


E8 


I NX 




A22D 


E8 


I NX 




A22E 


F01F "A24F 


BEQ 


:SSTB 


A230 


86A9 


STX 


STKLVL 


A232 


A5F2 


LDA 


CIX 


A234 


9D8004 


STA 


SIX.X 


A237 


A594 


LDA 


COX 


A239 


9D8104 


STA 


SOX,X 


A23C 


A59D 


LDA 


CPC 


A23E 


9D8204 


STA 


SPC.X 


A241 


A59E 


LDA 


CPC+1 


A243 


9D8304 


STA 


SPC+l.X 


A246 


68 


PLA 




A247 


859E 


STA 


CPC + 1 


A249 


68 


PLA 




A24A 


859D 


STA 


CPC 


A24C 


4CE2A1 


JMP 


:NEXT 


A24F 


4C24B9 


:SSTB JMP 


ERLTL 



GET STACK LEVEL 
PLUS 4 



;BR STACK TOO BIG 

; SAVE NEW STACK LEVEL 

CIX TO 
STACK IX 
COX TO 
STACK OX 
CPC TO 
STACK CPC 



MOVE STACKED 
PC TO CPC 



GO FOR NEXT 



POP 





= A252 


: POP EQU * 


A252 


A6A9 


LDX STKLVL 


A254 


D001 *A257 


BNE :POPl 



LOAD CPC FROM STACK PC 

AND DECREMENT TO PREV STACK LEVEL 



GET STACK LEVEL 

BR NOT TOP OF STACK 



152 



Source Code 



A256 60 



TO SYNTAX CALLER 



A257 BD8204 

A25A 859D 

A25C BD8304 

A25F 859E 

A261 CA 

A262 CA 

A263 CA 

A264 CA 

A265 86A9 

A267 B003 "A26C 

A269 4CE2A1 



P0P1 


LDA 


SPC.X 


STA 




CPC 


LDA 




SPC+l.X 


STA 




CPC+1 


DEX 






DEX 






DEX 






DEX 






STX 




STKLVL 


BCS 




:FAIL 


JMP 




:NEXT 



MOVE STACK PC 
TO CURRENT PC 



BR IF CALLER FAILING 
ELSE GO TO NEXT 



FAIL 





= A26C 


:FAIL EQU 


* 


A26C 


20AIA2 


JSR 


:NXSC 


A26F 


30FB ~A26C 


BMI 


:FAIL 


A271 


C902 


CMP 


#2 


A273 


B008 "A27D 


BCS 


:TSTOR 


A275 


209AA2 


JSR 


: INCCPC 


A278 


209AA2 


JSR 


: INCCPC 


A27B 


D0EF "A26C 


BNE 


:FAIL 


A27D 


C903 


:TSTOR CMP 


#3 


A27F 


F0D1 "A252 


BEQ 


:POP 


A281 


B0E9 "A26C 


BCS 


:FAIL 


A283 


A5F2 


LDA 


CIX 


A285 


C59F 


CMP 


MAXCIX 


A287 


9002 "A28B 


BCC 


:SCIX 


A289 


859F 


STA 


MAXCIX 


A28B 




:SCIX 




A28B 


A6A9 


LDX 


STKLVL 


A28D 


BD8004 


LDA 


SIX.X 


A290 


85F2 


STA 


CIX 


A292 


BD8104 


LDA 


SOX,X 


A295 


8594 


STA 


COX 


A297 


4CE2A1 


JMP 


:NEXT 



TERMINAL FAILED 

LOOK FOR ALTERNATIVE [OR] OR 

A RETURN INDICATOR 



GET NEXT CODE 



BR IF RNTV 

TEST CODE =2 

BR IF POSSIBLE OR 

CODE = OR 1 
INC PC BY TWO 
AND CONTINUE FAIL PROCESS 

TEST CODE=3 

BR CODE =3 [RETURN] 

CODE>3 [RNTV] CONTINUE 

IF THIS CIX 
IS A NEW MAX 

THEN SET NEW MAX 

CODE=2 [OR] 

MOVE STACK INDEXES 

TO CURRENT INDEXES 



TRY FOR SUCCESS HERE 



Increment CPC 



INCCPC - INC CPC BY ONE 





= A29A 


: INCCPC 


EQU * 


A29A 


E69D 


INC 


CPC 


A29C 


D002 "A2A0 


BNE 


: ICPCR 


A29E 


E69E 


INC 


CPC + 1 


A2A0 


60 


: ICPCR 


RTS 



NXSC 



GET NEXT SYNTAX CODE 



A2A1 




:NXSC 






A2A1 


209AA2 


JSR 


: INCCPC 


; INC PC 


A2A4 


A200 


LDX 


#0 




A2A6 


A19D 


LDA 


[CPC.X] 


; GET NEXT CODE 


A2A8 


60 


RTS 




; RETURN 



153 



Source Code 











TEST A 


TERMINAL CODE 


A2A9 






:TERMTST 






A2A9 


C90F 




CMP 


#S0F 


; TEST CODE=F 


A2AB 


F00D 


"A2BA 


BEQ 


:ECHNG 


; BR CODE < F 


A2AD 


B037 


"A2E6 


BCS 


: SRCONT 


; BR CODE > F 


A2AF 


68 




PLA 




; POP RTN ADR 


A2B0 


68 




PLA 






A2B1 


A90C 




LDA 


#:EXP-1&255 


; PUSH EXP ADR 


A2B3 


48 




PHA 




; FOR SPECIAL 


A2B4 


A9A6 




LDA 


*:EXP/256 


; EXP ANTV CALL 


A2B6 


48 




PHA 






A2B7 


4C28A2 


JMP 


: PUSH 


; GO PUSH 



ECHNG 



A2BA 




A2BA 


209AA2 


A2BD 


A000 


A2BF 


B19D 


A2C1 


A494 


A2C3 


88 


A2C4 


9180 


A2C6 


18 


A2C7 

SETCC 


60 

)DE 


A2C8 




A2C8 


A494 


A2CA 


9180 


A2CC 


E694 


A2CE 


F001 " 


A2D0 


60 


A2D1 


4C24B9 



EXTERNAL CODE TO CHANGE COX -1 

| INC PC TO CODE 

; GET CODE 

; GET COX 

; MINUS 1 

| SET NEW CODE 

; SET SUCCESS 

; RETURN 

SET CODE IN ACV AT COX AND INC COX 



GET COX 

SET CHAR 

INC COX 

BR IF NOT ZERO 

DONE 

GO TO LINE TOO LONG ERR 



HNG 




JSR 


: INCCPC 


LDY 


#0 


LDA 


[CPC],Y 


LDY 


COX 


DEY 




STA 


[OUTBUFF],Y 


CLC 




RTS 





SETCODE 






LDY 




COX 


STA 




[OUTBUFF],Y 


INC 




COX 


BEQ 




: SCOVF 


RTS 






SCOVF 


JMP 


ERLTL 



Exits for IF and REM 



A2D4 


A2FF 


EIF LDX 


#5FF 


A2D6 


9A 


TXS 




A2D7 


A594 


LDA 


COX 


A2D9 


A4A7 


LDY 


STMLBD 


A2DB 


9180 


STA 


[OUTBUFF], Y 


A2DD 


4CB1A0 


JMP 


:XIF 


A2E0 




EREM 




A2E0 




EDATA 




A2E0 


A2FF 


LDX 


#?FF 


A2E2 


9A 


TXS 




A2E3 


4CFBA0 


JMP 


: XDATA 


SRCONT 




SEARCH 


A2E6 




SRCONT 




A2E6 


20A1DB 


JSR 


SKPBLANK 


A2E9 


A5F2 


LDA 


CIX 


A2EB 


C5B3 


CMP 


SVONTX 


A2ED 


F016 "A305 


BEQ 


:SONTl 


A2EF 


85B3 


STA 


SVONTX 


A2F1 


A9A7 


LDA 


SOPNTAB/256 


A2F3 


A0E3 


LDY 


#OPNTABS,255 


A2F5 


A200 


LDX 


#0 


A2F7 


2062A4 


JSR 


SEARCH 



; RESET STACK 

; SET STMT LENGTH 

I GO CONTINUE IF 

; RESET STACK 
;GO CONTINUE DATA 

SEARCH OP NAME TABLE AND TEST RESULT 



SKIP BLANKS 

GET CURRENT INPUT INDEX 
COMPARE WITH SAVED IX 
BR IF SAVED IX SAME 
SAVE NEW IX 

SET UP FOR ONT 
SEARCH 

GO SEARCH 



154 



Source Code 



A2FA 


B028 


"A324 


BCS 




:SONF 


BR NOT FOUND 


A2FC 


86B2 




STX 




SVONTL 


SAVE NEW CIX 


A2FE 


18 




CLC 








A2FF 


A5AF 




LDA 




STENUM 


ADD 510 TO 


A301 


6910 




ADC 




#510 


ENTRY NUMBER TO 


A303 


85B0 




STA 




SVONTC 


GET OPERATOR CODE 


A305 


A000 




:SONTl 


LDY 


#0 




A307 


B19D 




LDA 




[CPC], Y 


GET SYNTAX REQ CODE 


A309 


C5B0 




CMP 




SVONTC 


DOES IT MATCH THE FOUND 


A30B 


F00E 


"A31B 


BEQ 




:SONT2 


BR IF MATCH 


A30D 


C944 




CMP 




#CNFNP 


WAS REQ NFNP 


A30F 


D006 


~A317 


BNE 




: SONTF 


BR IF NOT 


A311 


A5B0 




LDA 




SVONTC 


GET WHAT WE GOT 


A313 


C944 




CMP 




#CNFNP 


IS IT NFNA 


A315 


B002 


"A319 


BCS 




: SONTS 


BR IF IT IS 


A317 






: SONTF 








A317 


38 




SEC 






REPORT FAIL 


A318 


60 




RTS 








A319 


A5B0 




: SONTS 


LDA 


SVONTC 


GET REAL CODE 


A31B 


20C8A2 


:SONT2 


JSR 


:SETCODE 


GO SET CODE 


A3 IE 


A6B2 




LDX 




SVONTL 


INC CIX BY 


A320 


86F2 




STX 




CIX 




A322 


18 




CLC 






REPORT SUCCESS 


A323 


60 




RTS 






DONE 


A324 


A900 




:SONF_ 


LDA 


#0 


SET ZERO AS 


A326 


85B0 




STA 




SVONTC 


SAVED CODE 


A328 


38 




SEC 








A329 


60 




RTS 






DONE 



TVAR 

A32A 
A32C 



A900 

F002 ~A330 



TNVAR LDA #0 
BEQ :TVAR 



EXTERNAL SUBROUTINE FOR TNVAR & TSVAR 
; SET NUMERIC TEST 



A32E A980 



TSVAR LDA 



#580 



A330 


85D2 




:TVAR 


STA 


TVTYPE 


A332 


20A1DB 


JSR 




SKPBLANK 


A335 


A5F2 




LDA 




CIX 


A337 


85AC 




STA 




TVSCIX 


A339 


20F3A3 


JSR 




rTSTALPH 


A33C 


B025 


"A363 


BCS 




:TVFAIL 


A33E 


20E6A2 


JSR 




:SRCONT 


A341 


A5B0 




LDA 




SVONTC 


A343 


F008 


"A34D 


BEQ 




:TV1 


A345 


A4B2 




LDY 




SVONTL 


A347 


B1F3 




LDA 




[INBUFF],Y 


A349 


C930 




CMP 




#$30 


A34B 


9016 


~A363 


BCC 




:TVFAIL 


A34D 


E6F2 




:TV1 


INC 


CIX 


A34F 


20F3A3 


JSR 




:TSTALPH 


A352 


90F9 


"A34D 


BCC 




:TV1 


A354 


20AFDB 


JSR 




TSTNUM 


A357 


90F4 


"A34D 


BCC 




:TV1 


A359 


B1F3 




LDA 




[INBUFF], Y 


A35B 


C924 




CMP 




#'$' 


A35D 


F006 


"A365 


BEQ 




:TVSTR 


A35F 


24D2 




BIT 




TVTYPE 


A361 


1009 


"A36C 


BPL 




:TVOK 


A363 


38 




:TVFAIL 


SEC 




A364 


60 




RTS 






A365 


24D2 




:TVSTR 


BIT 


TVTYPE 


A367 


10FA 


~A363 


BPL 




:TVFAIL 



SET STR TEST 

SAVE TEST TYPE 
SKIP LEADING BLANKS 
GET INDEX 
FOR SAVING 

GO TEST FIRST CHAR 
BR NOT ALPHA 
IF THIS IS A 
RESVD NAME 
BR NOT RSVDNAME 
IF NEXT CHAR AFTER 
RESERVED NAME 
NOT ALARM NUMERIC 
THEN ERROR 

INC TO NEXT CHAR 
TEST ALPHA 
BR IF ALPHA 
TRY NUMBER 
BR IF NUMBER 

GET OFFENDING CHAR 
IS IT 5 

BR IF 5 [STRING] 
THIS A NVAR SEARCH 
BR 'IF NVAR 

SET FAIL CODE 
DONE 

TEST SVAR SEARCH 
BR IF SVAR 



155 



Source Code 



A369 CS 

A36A D00D ~A379 



INY 

BNE 



:TVOK2 



INC OVER $ 
BR ALWAYS 



A36C 


B1F3 


:TVOK LDA 


[INBUFF' 


A36E 


C928 


CMP 


#'(' 


A370 


D007 *A379 


BNE 


:TVOK2 


A372 


C8 


INY 




A373 


A940 


LDA 


#$40 


A375 


05D2 


ORA 


TVTYPE 


A377 


85D2 


STA 


TVTYPE 


A379 


A5AC 


:TV0K2 LDA 


TVSCIX 


A37B 


85F2 


STA 


CIX 


A37D 


84AC 


STY 


TVSCIX 


A37F 


A583 


LDA 


VNTP+1 


A381 


A482 


LDY 


VNTP 


A383 


A200 


LDX 


#0 


A385 


2062A4 


JSR 


SEARCH 


A388 




:TVRS 




A388 


B00A "A394 


BCS 


:TVS0 


A38A 


E4AC 


CPX 


TVSCIX 


A38C 


F04D "A3DB 


BEQ 


:TVSUC 


A38E 


2090A4 


JSR 


SRCNXT 


A391 


4C88A3 


JMP 


:TVRS 


A394 




:TVS0 




A394 


38 


SEC 




A395 


A 5 AC 


LDA 


TVSCIX 


A397 


E5F2 


SBC 


CIX 


A399 


85F2 


STA 


CIX 


A39B 


A8 


TAY 




A39C 


A284 


LDX 


#VNTD 


A39E 


207FA8 


JSR 


EXPLOW 


A3A1 


A5AF 


LDA 


STENUM 


A3A3 


85D3 


STA 


TVNUM 


A3A5 


A4F2 


LDY 


CIX 


A3A7 


88 


DEY 




A3A8 


A6AC 


LDX 


TVSCIX 


A3AA 


CA 


DEX 




A3AB 


BD8005 


:TVS1 LDA 


LBUFF.X 


A3AE 


9197 


STA 


[SVESA], Y 


A3B0 


CA 


DEX 




A3B1 


88 


DEY 




A3B2 


10F7 "A3AB 


BPL 


:TVS1 


A3B4 


A4F2 


LDY 


CIX 


A3B6 


88 


DEY 




A3B7 


B197 


LDA 


[SVESA], Y 


A3B9 


0980 


ORA 


#$80 


A3BB 


9197 


STA 


[SVESA], Y 



A3BD A008 

A3BF A288 

A3C1 207FA8 

A3C4 E6B1 



A3C6 
A3C8 
A3CA 
A3CD 
A3CE 
A3D0 
A3D2 
A3D3 
A3D6 
A3D8 
A3D9 



LDY 
LDX 
JSR 
INC 



#8 

#STMTAB 
EXPLOW 
SWVTE 



A002 

A900 

99D200 

C8 

C008 

90F8 "A3CA 

88 

B9D200 

9197 

88 

10F8 "A3D3 



LDY #2 

LDA #0 
:TVS1A STA 

INY 

CPY #8 

BCC :T 

DEY 
:TVS2 LDA 

STA 

DEY 

BPL 



TVTYPE, Y 



TVTYPE, Y 
[SVESA], Y 



; GET NEXT CHAR 
IS IT PAREN 
BR NOT PAREN 
INC OVER PAREN 
OR IN ARRAY 
CODE TO TVTYPE 



GET SAVED CIX 
PUT BACK 
SAVE NEW CIX 



SEARCH VNT 
FOR THIS GUY 



BR NOT FOUND 
FOUND RIGHT ONE 
BR IF YES 
GO SEARCH MORE 
TEST THIS RESULT 



SIGH: 

VAR LENGTH IS 

NEW CIX-OLD CIX 



GO EXPAND VNT 
BY VAR LENGTH 

SET VARIABLE NUMBER 

AND 

GET DISPL TO EQU+1 

MOVE VAR TO 



TURN ON MSB 
OF LAST CHAR 
IN VTVT ENTRY 



THEN EXPAND 
WT BY 8 

INC WT EXP SIZE 

CLEAR VALUE 
PART OF 
ENTRY 



AND THEN 

PUT IN VAR TABLE 

ENTRY 



156 



Source Code 



A3DB 24D2 

A3DD 5002 "A3E1 

A3DF C6AC 



:TVSUC BIT TVTYPE 
BVC :TVNP 
DEC TVSCIX 



WAS THERE A PAREN 

BR IF NOT 

LET SYNTAX SEE PAREN 



A3E1 


A5AC 




:TVNP 


LDA 


TVSCIX 


; GET NEW CIX 


A3E3 


85F2 




STA 




CIX 


; TO CIX 


A3E5 


A5AF 




LDA 




STENUM 


; GET TABLE ENTRY NO 


A3E7 


3007 * 


A3F0 


BMI 




:TVFULL 


r BR IF > S7F 


A3E9 


0980 




ORA 




#?80 


; MAKE IT > S7F 


A3EB 


20C8A2 




JSR 




:SETCODE 


; SET CODE TO OUTPUT BUFFER 


A3EE 


18 




CLC 






; SET SUCCESS CODE 


A3EF 


60 




RTS 






; RETURN 


A3F0 


4C38B9 




:TVFULL 


JMP 


ERRVSF 


; GO TO ERROR RTN 


TSTALPH 






















TEST CIX 


FOR ALPHA 


A3F3 






: TSTALPH 






A3F3 


A4F2 




LDY 




CIX 




A3F5 


B1F3 




LDA 




[INBUFF], Y 




A3F7 






TSTALPH 








A3F7 


C941 




CMP 




i'ft 




A3F9 


9003 " 


A3FE 


BCC 




:TAFAIL 




A3FB 


C95B 




CMP 




#$5B 




A3FD 


60 




RTS 








A3FE 


3B 




:TAFAIL 


SEC 






A3FF 


60 




RTS 









TNCON 



A400 
A400 
A403 
A405 
A407 
A40A 
A40C 
A40E 
A410 



20A1DB 

A5F2 

85AC 

2000D8 

9005 "A411 

A 5 AC 

85F2 

60 



TNCON 
JSR 
LDA 
STA 
JSR 
BCC 
LDA 
STA 
RTS 



EXTERNAL SUBROUTINE TO CHECK FOR NUMBER 



SKBLANK 

CIX 

TVSCIX 

CVAFP 

:TNCI 

TVSCIX 

CIX 



,- GO TEST AND CONV 
; BR IF NUMBER 



; RETURN FAIL 



A411 

A413 



A90E 
20C8A2 



:TNC1 LDA #$0E 
JSR :SETCODE 



SET NUMERIC CONST 



A416 
A418 
A41A 
A41C 
A41E 
A41F 
A420 
A422 
A424 
A426 
A42 7 



A494 

A200 

B5D4 

9180 

C8 

ES 

E006 

90F6 

8494 

18 

60 



LDY 




COX 


LDX 




#0 


2 


LDA 


FR0,X 


STA 




[OUTBUFF], Y 


I NY 






I NX 






CPX 




#6 


BCC 




:TNC2 


STY 




COX 


CLC 






RTS 







; MOVE CONST TO STMT 



TSCON 



A428 




A42 8 


20A1DB 


A42B 


A4F2 


A42D 


B1F3 


A42F 


C922 


A431 


F002 " 


A433 


38 


A434 


6 



TSCON 




JSR 


SKBLANK 


LDY 


CIX 


LDA 


[INBUFF], Y 


CMP 


#$22 


BEQ 


:TSC1 


SEC 




RTS 





EXT SRT TO CHECK FOR STR CONST 



GET INDEX 
GET CHAR 
IS IT DQUOTE 
BR IF DQ 
SET FAIL 
RETURN 



157 



Source Code 



A435 


A90F 


:TSC1 


LDA 


#$0F 


; SET SCON CODE 


A437 


20C8A2 


JSR 




:SETCODE 




A43A 


A594 


LDA 




COX 


; SET COX 


A43C 


85AB 


STA 




TSCOX 


; SAVE FOR LENGTH 


A43E 


20C8A2 


JSR 




:SETCODE 


; SET DUMMY FOR NOW 


A441 


E6F2 


:TSC2 


INC 


CIX 


; NEXT INPUT CHAR 


A443 


A4F2 


LDY 




CIX 




A445 


B1F3 


LDA 




[INBUFF],Y 




A447 


C99B 


CMP 




#CR 


; IS IT CR 


A449 


F00C "A457 


BEQ 




:TSC4 


; BR IF CR 


A44B 


C922 


CMP 




#$22 


; IS IT DQ 


A44D 


F006 "A455 


BEQ 




:TSC3 


; BR IF DQ 


A44F 


20C8A2 


JSR 




:SETCODE 


; OUTPUT IT 


A452 


4C41A4 


JMP 




:TSC2 


; NEXT 


A455 


E6F2 


:TSC3 


INC 


CIX 


; INC CIX OVER DQ 


A457 


18 


:TSC4 


CLC 






A458 


A594 


LDA 




COX 


; LENGTH IS COX MIN 


A45A 


E5AB 


SBC 




TSCOX 


; LENGTH BYTE COX 


A45C 


A4AB 


LDY 




TSCOX 




A45E 


9180 


STA 




[OUTBUFF],Y 


; SET LENGTH 


A460 


18 


CLC 






; SET SUCCESS 


A461 


60 


RTS 






; DONE 



Search a Table 



TABLE FORMAT: 

GARBAGE TO SKIP [N] 
ASCII CHAR [N] 

WITH LEAST SIGNIFICANT BYTE HAVING 
MOST SIGNIFICANT BIT ON 
LAST TABLE ENTRY MUST HAVE FIRST ASCII 
CHAR = 

ENTRY PARMS: 

Y. = SKIP LENGTH 

A,Y = TABLE ADR [HIGH LOW] 

ARGUMENT = INBUFF + CIX 
EXIT PARMS: 

CARRY = CLEAR IF FOUND 

X = FOUND ARGUMENT END CIX+1 

SRCADR = TABLE ENTRY ADR 

STENUM = TABLE ENTRY NUMBER 



A462 






SEARCH 




A46 2 


86AA 




STX 


SRCSKP 


A464 


A2FF 




LDX 


#?FF 


A466 


86AF 




STX 


STENUM 


A468 


8596 




-. SRC1 STA 


SRCADR+1 


A46A 


8495 




STY 


SRCADR 


A46C 


E6AF 




INC 


STENUM 


A46E 


A6F2 




LDX 


CIX 


A470 


A4AA 




LDY 


SRCSKP 


A472 


B195 




LDA 


[SRCADR], Y 


A474 


F027 


"A49D 


BEQ 


:SRCNF 


A476 


A900 




LDA 


#0 


A478 


08 




PHP 




A479 


BD8005 


•SRC2 LDA 


LBUFF.X 


A47C 


297F 




AND 


#?7F 


A47E 


C92E 




CMP 


# ' . ' 


A480 


F01D 


"A49F 


BEQ 


:SRC5 


A482 






:SRC2A 




A482 


5195 




EOR 


[SRCADR], Y 


A484 






ASLA 




A484 


+0A 




ASL 


A 


A485 


F002 


"A489 


BEQ 


:SRC3 



SAVE SKIP FACTOR 

SET ENTRY NUMBER 
TO ZERO 

SET SEARCH ADR 

INC ENTRY NUMBER 
GET ARG DISPL 
GET SKIP LENGTH 
GET FIRST CHAR 
BR IF EOT 
SET STATUS = EQ 
AND PUSH IT 

GET INPUT CHAR 
TURN OFF MSB 
IF WILD CARD 
THEN BR 

EX-OR WITH TABLE CHAR 
SHIFT MSB TO CARRY 

BR IF [ARG=TAB] CHAR 



158 



Source Code 



A487 


68 




PLA 






; POP STATUS 


A488 


08 




PHP 






1 PUSH NE STATUS 


A489 


C8 




:SRC3 


INY 




;INC TABLE INDEX 


A48A 


E8 




INX 






;INC ARG INDEX 


A48B 


90EC 


*A479 


BCC 




:SRC2 


; IF TABLE MSB OFF, CO 
;ELSE END OF ENTRY 


A48D 


28 




PLP 






;GET STATUS 


A48E 


F00B 


"A49B 


BEQ 




: SRCFND 


rBR IF NO MIS MATCH 


A490 






SRCNXT 








A490 


18 




CLC 








A491 


98 




TYA 






;ACV=ENTRY LENGTH 


A492 


6595 




ADC 




SRCADR 


;PLUS START ADR [L] 


A494 


A8 




TAY 






:TO Y 


A495 


A596 




LDA 




SRCADR+1 


;ETC 


A497 


6900 




ADC 




#0 




A499 


D0CD 


"A468 


BNE 




:SRC1 


;BR ALLWAYS 


A49B 


18 




:SRCFND 


CLC 




; INDICATE FOUND 


A49C 


60 




RTS 








A49D 


38 




:SRCNF 


SEC 




; INDICATE NOT FOUND 


A49E 


60 




RTS 








A49F 


A902 




!sRC5 


LDA 


#2 


; IF NOT 


A4A1 


C5AA 




CMP 




SRCSKP 


; STMT NAME TABLE 


A4A3 


D0DD 


"A482 


BNE 




:SRC2A 


; THEN IGNORE 


A4A5 


B195 




:SRC6 


LDA 


[SRCADR],Y 


;TEST MSB OF TABLE 


A4A7 


3003 


"A4AC 


BMI 




:SRC7 


; IF ON DONE 


A4A9 


C8 




INY 






; ELSE 


A4AA 


D0F9 


"A4A5 


BNE 




:SRC6 


; LOOK AT NEXT CHAR 


A4AC 


38 




:SRC7 


SEC 




; INDICATE MSB ON 


A4AD 


B0DA 


~A489 


BCS 




:SRC3 


; AND RE-ENTER CODE 



Statement Name Table 



A4AF 



SNTAB- STATEMENT NAME TABLE 

EACH ENTRY HAS SYNTAX TABLE ADR PTR 
FOLLOWED BY STMT NAME 



A4AF 


C7A7 


DW 


:SREM-1 


A4B1 


5245CD 


DC 


'REM' 


A4B4 


CAA7 


DW 


:SDATA-1 


A4B6 


444154C1 


DC 


' DATA ' 


A4BA 


F3A6 


DW 


:SINPUT-1 


A4BC 


494E5055D4 


DC 


'INPUT' 


A4C1 


BCA6 


DW 


:SCOLOR-l 


A4C3 


434F4C4FD2 


DC 


'COLOR' 


A4C8 


32A7 


DW 


:SLIST-1 


A4CA 


4C4953D4 


DC 


'LIST' 


A4CE 


23A7 


DW 


:SENTER-1 


A4D0 


454E5445D2 


DC 


'ENTER' 


A4D5 


BFA6 


DW 


:SLET-1 


A4D7 


4C45D4 


DC 


'LET' 


A4DA 


93A7 


DW 


:SIF-1 


A4DC 


49C6 


DC 


'IF' 


A4DE 


D1A6 


DW 


:SFOR-l 


A4E0 


464FD2 


DC 


'FOR' 


A4E3 


E9A6 


DW 


:SNEXT-1 



159 



Source Code 



A4E5 4E4558D4 



A4E9 


BCA6 


DW 


:SG0T0-1 


A4EB 


474F54CF 


DC 


' GOTO ' 


A4EF 


BCA6 


DW 


:SGOTO-l 


A4F1 


474F2054CF 


DC 


'GO TO' 


A4F6 


BCA6 


DW 


:SGOSUB-l 


A4F8 


474F5355C2 


DC 


'GOSUB' 


A4FD 


BCA6 


DW 


:STRAP-1 


A4FF 


545241D0 


DC 


'TRAP' 


A503 


BDA6 


DW 


:SBYE-1 


A505 


4259C5 


DC 


'BYE' 


A508 


BDA6 


DW 


:SCONT-l 


A50A 


434F4ED4 


DC 


' CONT ' 


A50E 


5FA7 


DW 


:SCOM-l 


A510 


434FCD 


DC 


'COM' 


A513 


20A7 


DW 


:SCLOSE-l 


A515 


434C4F53C5 


DC 


'CLOSE' 


A51A 


BDA6 


DW 


:SCLR-1 


A51C 


434CD2 


DC 


'CLR' 


A51F 


BDA6 


DW 


:SDEG-1 


A521 


4445C7 


DC 


'DEC 


A524 


5FA7 


DW 


iSDXM-1 


A526 


4449CD 


DC 


'DIM' 


A529 


BDA6 


DW 


:SEND-1 


A52B 


454EC4 


DC 


'END' 


A52E 


BDA6 


DW 


:SNEW-1 


A530 


4E45D7 


DC 


'NEW' 


A533 


19A7 


DW 


:SOPEN-l 


A535 


4F5045CE 


DC 


'OPEN' 


A539 


23A7 


DW 


:SL0AD-1 


A53B 


4C4F4104 


DC 


'LOAD' 


A53F 


23A7 


DW 


:SSAVE-1 


A541 


534156C5 


DC 


'SAVE' 


A545 


40A7 


DW 


:SSTATUS-1 


A547 


5354415455 
D3 


DC 


' STATUS ' 


A54D 


49A7 


DW 


:SNOTE-l 


A54F 


4E4F54C5 


DC 


' NOTE ' 


A553 


49A7 


DW 


:SPOINT-l 


A555 


504F494ED4 


DC 


'POINT ' 


A55A 


17A7 


DW 


:SXIO-l 


A55C 


5849CF 


DC 


'XIO' 


A55F 


62A7 


DW 


:SON-l 


A561 


4FCE 


DC 


'ON' 


A563 


5CA7 


DW 


:SPOKE-l 


A565 


504F4BC5 


DC 


' POKE ' 


A569 


FBA6 


DW 


:SPRINT-1 


A56B 


5052494ED4 


DC 


'PRINT ' 


A570 


BDA6 


DW 


:SRAD-1 


A572 


5241C4 


DC 


'RAD' 


A575 


F4A6 


DW 


:SREAD-1 



160 



Source Code 



A577 


524541C4 


A57B 


EEA6 


A57D 


524553544F 




52C5 


A584 


BDA6 


A586 


5245545552 




CE 


A58C 


26A7 


A58E 


5255CE 


A591 


BDA6 


A593 


53544FD0 


A597 


BDA6 


A599 


504FD0 


A59C 


FBA6 


A59E 


BF 


A59F 


E7A6 


A5A1 


4745D4 


A5A4 


B9A6 


A5A6 


5055D4 


A5A9 


BCA6 


A5AB 


4752415048 




4943D3 


A5B3 


5CA7 


A5B5 


504C4FD4 


A5B9 


5CA7 


A5BB 


504F534954 




494FCE 


A5C3 


BDA6 


A5C5 


444FD3 


A5C8 


5CA7 


A5CA 


4452415754 




CF 


A5D0 


5AA7 


A5D2 


534554434F 




4C4FD2 


A5DA 


E1A6 


A5DC 


4C4F434154 




C5 


A5E2 


58A7 


A5E4 


534F554EC4 


A5E9 


FFA6 


A5EB 


4C5052494E 




D4 


A5F1 


BDA6 


A5F3 


43534156C5 


A5F8 


BDA6 


A5FA 


434C4F41C4 


A5FF 


BFA6 


A601 


00 


A602 


8000 


A604 


2A4552524F 




522D20 


A60C 


A0 



DW 

DC 



DW 
DC 



DW 
DC 

DW 
DC 

DW 
DC 

DW 
DC 

DW 
DC 

DW 
DC 

DW 
DC 



DW 
DC 



DW 
DC 



DW 
DC 



DW 
DC 



DW 

DC 



DW 

DC 



DW 
DC 
DW 
DC 

DW 
DC 

DW 
DC 
DW 
DB 

DB 
DB 



:SREST-1 
'RESTORE' 



:SRET-1 
'RETURN' 



:SRUN-1 
'RUN' 

:SSTOP-l 
' STOP ' 

:SPOP-l 
'POP' 

:SPRINT-1 
'?' 

:SGET-1 

'GET' 

:SPUT-1 

'PUT ' 

:SGR-1 

'GRAPHICS' 



:SPLOT-l 
1 PLOT ' 



:SPOS-l 
'POSITION' 



:SDOS-l 
'DOS ' 



:SDRAWTO-l 
' DRAWTO ' 



:SSETCOLOR-l 
'SETCOLOR' 



:SLOCATE-l 
'LOCATE' 



:SSOUND-l 
'SOUND' 
:SLPRINT-1 
'LPRINT' 

:SCSAVE-1 

'CSAVE ' 

:SCLOAD-l 

'CLOAD' 

:SILET-1 



580,00 

' * ERROR- ' 



$A0 



161 



Source Code 



Syntax Tables 



Syntax Table OP Codes 



= 


0000 


= 


0001 


= 


0002 


= 


0003 


= 


0004 


= 


000E 


= 


000F 


<EXP> =(< 


A60D 




A60D 


+2B 


A60E 




A60E 


+BF 


A60F 




A60F 


+2C 


A610 




A610 


+DE 


A611 




A611 


+0 2 


A612 




A612 


+C6 


A613 




A613 


+BA 


A614 




AG14 


+0 2 


A615 




A615 


+CD 


A616 




A616 


+D8 


A617 




A617 


+03 


<UNARY> 


A618 




A618 


+25 


A619 




A619 


+0F 


A61A 


+35 


A61B 




A61B 


+02 


A61C 




A61C 


+26 


A61D 




A61D 


+0F 


A61E 


+36 


A61F 




A61F 


+02 


A620 




A620 


+28 


A621 




A621 


+03 


<IMV 


> = < 


A622 




A622 


+FD 


A623 


+02 


A624 




A624 


+E8 


A625 


+02 


A626 




A626 


+01 



ANTV 


EQU 


$00 


ESRT 


EQU 


$01 


OR 


EQU 


$02 


RTN 


EQU 


$03 


NULL 


EQU 


$04 


VEXP 


EQU 


$0E 


CHNG 


EQU 


$0F 



ABSOLUTE NON TERMINAL VECTOR 
FOLLOWED BY 2 BYTE ADR -1 

EXTERNAL SUBROUTINE CALL 

FOLLOWED BY 2 BYTE ADR -1 

ALTERNATIVE, BNF OR (]) 

RETURN, (#) 

ACCEPT TO THIS POINT ( s, ) 

SPECIAL NTV FOR EXP (<EXP>) 

CHANGE LAST OUTPUT TOKEN 



(<EXP>)<NOP> | <UNARYxEXP> | <NV><NOP># 



SYN 


CLPRN 




DB 


CLPRN 




SYN 


JS, :EXP 




DB 


$80+( ( (:EXP-* 


&$7F) XOR $40 ) 


SYN 


CRPRN 




DB 


CRPRN 




SYN 


JS, :NOP 




DB 


$80+( ( ( :NOP-* 


6,$7F) XOR $40 ) 


SYN 


:OR 




DB 


:0R 




SYN 


JS, : UNARY 




DB 


$80+ ( ( ( : UNARY 


-*)S,$7F) XOR $40 ) 


SYN 


JS, :EXP 




DB 


$80+( ( ( :EXP-* 


&$7F) XOR $40 ) 


SYN 


:OR 




DB 


:OR 




SYN 


JS, :NV 




DB 


$80+( ( ( :NV-*) 


«$7F) XOR $40 ) 


SYN 


JS, :NOP 




DB 


$80+( ( ( :NOP-* 


&$7F) XOR $40 ) 


SYN 


:RTN 




DB 


:RTN 





+ I - I NOT# 



UNARY SYN 


CPLUS 


DB 


CPLUS 


SYN 


:CHNG,CUPLUS 


DB 


:CHNG 


DB 


CUPLUS 


SYN 


:OR 


DB 


:OR 


SYN 


CMINUS 


DB 


CMINUS 


SYN 


:CHNG,CUMINUS 


DB 


:CHNG 


DB 


CUMINUS 


SYN 


:OR 


DB 


:OR 


SYN 


CNOT 


DB 


CNOT 


SYN 


:RTN 


DB 


:RTN 



<NVAR> <NCON> | <STCOMP># 

:NV SYN JS, :NFUN, : OR 

DB $80+( ( ( :NFUN-*)&$7F) XOR $40 ) 

DB :OR 

SYN JS, :NVAR, : OR 

DB $80+( ( ( :NVAR-*)&$7F) XOR $40 ) 

DB :OR 
SYN :ESRT, AD, :TNCON-l, : OR 

DB :ESRT 



162 



Source Code 



A627 +FFA3 

A629 +02 
A62A 

A62A +00 

A62B +7DA6 
A62D 

A62D +03 

<NOP> = < 

A62E 

A62E +C4 
A62F 

A62F +9E 
A630 

A630 +02 
A631 
A631 +03 



<OP> = ** | * ] /| < 



A632 




A632 


+23 


A633 


+02 


A634 




A634 


+25 


A635 


+02 


A636 




A636 


+26 


A637 


+02 


A638 




A638 


+24 


A639 


+02 


A63A 




A63A 


+ 27 


A63B 


+02 


A63C 




A63C 


+1D 


A63D 


+0 2 


A63E 




A63E 


+1F 


A63F 


+02 


A640 




A640 


+ 1E 


A641 


+02 


A642 




A642 


+20 


A643 


+02 


A644 




A644 


+21 


A645 


+02 


A646 




A646 


+22 


A647 


+02 


A648 




A648 


+ 2A 


A649 


+0 2 


A64A 




A64A 


+ 29 


A64B 




A64B 


+03 


<NVAR> = 


A64C 




A64C 


+01 


A64D 


+ 29A3 


A64F 




A64F 


+C2 


A650 




A650 


+0 3 



DW 


( :TNCON-l ) 


DB 


:OR 


SYN 


:ANTV,AD, :STCOMP-l 


DB 


:ANTV 


DW 


( :STCOMP-l) 


SYN 


:RTN 


DB 


:RTN 


EXP> | &# 




NOP SYN 


JS, :OP 


DB 


580+( ( ( :OP-*)&$7F) XOR $40 ) 


SYN 


JS, :EXP 


DB 


$80+( ( ( :EXP-*)&$7F) XOR $40 ) 


SYN 


:OR 


DB 


:OR 


SYN 


:RTN 


DB 


:RTN 


:= | S= | <> | < | > |= | AND | OR# 


OP SYN 


CEXP, :OR 


DB 


CEXP 


DB 


:OR 


SYN 


CPLUS, :OR 


DB 


CPLUS 


DB 


:OR 


SYN 


CMINUS, :OR 


DB 


CMINUS 


DB 


:OR 


SYN 


CMUL, :OR 


DB 


CMUL 


DB 


:0R 


SYN 


CDIV, :OR 


DB 


CDIV 


DB 


:OR 


SYN 


CLE, :OR 


DB 


CLE 


DB 


:OR 


SYN 


CGE, :OR 


DB 


CGE 


DB 


:OR 


SYN 


CNE, :0R 


DB 


CNE 


DB 


:OR 


SYN 


CLT, :OR 


DB 


CLT 


DB 


:OR 


SYN 


CGT, :OR 


DB 


CGT 


DB 


:OR 


SYN 


CEQ, :OR 


DB 


CEQ 


DB 


:OR 


SYN 


CAND, :OR 


DB 


CAND 


DB 


:OR 


SYN 


COR 


DB 


COR 


SYN 


:RTN 


DB 


:RTN 



<TNVAR> <NMAT># 



:ESRT, AD, :TNVAR-1 



DB 


:ESRT 




DW 


( :TNVAR-1 ) 




SYN 


JS, :NMAT 




DB 
SYN 


$80+ ( ( ( :NMAT-*' 
:RTN 


)&$7F) XOR 


DB 


:RTN 





S40 ) 



163 



Source Code 



<NMAT> = ( <EXP> <NMAT2> ) | &# 



A651 






: NMAT SYN 


CLPRN, :CHNG,CALPRN 


A651 


+2B 




DB 


CLPRN 


A652 


+0F 




DB 


:CHNG 


A653 


+3 8 




DB 


CALPRN 


A654 






SYN 


:VEXP 


A654 


+0E 




DB 


:VEXP 


A655 






SYN 


JS, :NMAT2 


A655 


+C4 




DB 


$80+((( :NMAT2-*)&$7F) XOR $40 ) 


A656 






SYN 


CRPRN 


A656 


+2C 




DB 


CRPRN 


A657 






SYN 


:0R 


A657 


+02 




DB 


:0R 


A658 






SYN 


:RTN 


A658 


+0 3 




DB 


:RTN 


<NMAT2> 


= ,<EXP> | &# 




A659 






: NMAT 2 SYN 


CCOM, :CHNG,CACOM 


A659 


+12 




DB 


CCOM 


A65A 


+0F 




DB 


:CHNG 


A65B 


+3C 




DB 


CACOM 


A65C 






SYN 


:VEXP 


A65C 


+0E 




DB 


:VEXP 


A65D 






SYN 


:OR 


A65D 


+02 




DB 


:OR 


A65E 






SYN 


:RTN 


A65E 


+03 




DB 


:RTN 


<NFUN> = 


<NFNP><NFP> | <NFSP><SFP> | <NFUSR># 


A65F 






:NFUN SYN 


CNFNP 


A65P 


+44 




DB 


CNFNP 


A660 






SYN 


JS, :NFP 


A660 


+D2 




DB 


$80+( ( ( :NFP-*)&$7F) XOR $40 ) 


A661 






SYN 


:OR 


A661 


+02 




DB 


:OR 


A662 






SYN 


:ANTV, AD, :NFSP-1 


A662 


+00 




DB 


:ANTV 


A663 


+CDA7 




DW 


( :NFSP-1) 


A665 






SYN 


JS, :SFP 


A665 


+D3 




DB 


$80+( ( ( :SFP-*)S,$7F) XOR $40 ) 


A666 






SYN 


:OR 


A666 


+02 




DB 


:OR 


A667 






SYN 


JS, :NFUSR 


A667 


+C2 




DB 


$80+( (( :NFUSR-*)&$7F) XOR $40 ) 


A668 






SYN 


:RTN 


A668 


+03 




DB 


:RTN 


<NFUSR> = 


= USR( 


<PUSR> )# 




A669 






:NFUSR SYN 


CUSR 


A669 


+3F 




DB 


CUSR 


A66A 






SYN 


CLPRN, :CHNG, CFLPRN 


A66A 


+2B 




DB 


CLPRN 


A66B 


+0F 




DB 


:CHNG 


A66C 


+3A 




DB 


CFLPRN 


A66D 






SYN 


:ANTV, AD, :PUSR-1 


A66D 


+00 




DB 


:ANTV 


A66E 


+D9A7 




DW 


( :PUSR-1) 


A670 






SYN 


CRPRN 


A670 


+2C 




DB 


CRPRN 


A671 






SYN 


:RTN 


A671 


+03 




DB 


:RTN 


<NFP> = ( <EXP> )# 




A672 






:NFP SYN 


CLPRN, :CHNG, CFLPRN 


A672 


+2B 




DB 


CLPRN 


A673 


+0F 




DB 


:CHNG 


A674 


+3A 




DB 


CFLPRN 


A675 






SYN 


:VEXP 



164 



Source Code 



A67 5 +0E DB 

A676 SYN 
A676 +2C DB 

A677 SYN 
A677 +03 DB 

<SFP> = <STR> )# 

A678 tS 

A678 +2B 

A679 +0F DB 

A67A +3A DB 

A67B SYN 

A67B +C7 DB 

A67C SYN 
A67C +2C DB 

A67D SYN 
A67D +03 DB 



:VEXP 
CRPRN 

CRPRN 
:RTN 

:RTN 



SYN CLPRN, :CHNG,CFLPRN 
DB CLPRN 
:CHNG 
CFLPRN 

JS, :STR 
S80+( ( ( :STR-*)&$7F) XOR $40 

CRPRN 
CRPRN 

:RTN 
:RTN 



<STCOMP> = <STR> <SOP> <STR># 



A67E 

A67E +C4 
A67F 

A67F +E3 
A680 

A680 +C2 
A681 
A681 +03 



:STCOMP SYN JS, :STR 

DB $80+( ( ( :STR-*)&?7F) XOR $40 ) 

SYN JS, :SOP 

DB $80+( ( ( :SOP-*)S,$7F) XOR $40 ) 

SYN JS, :STR 

DB $80+( ( ( :STR-*)&$7F) XOR $40 ) 

SYN : RTN 

DB : RTN 



<STR> = <SFUN> | <SVAR> | <SCON># 



A682 




:STR SYN 


JS, :SFUN 


A682 +C8 




DB 


$80+ ( ( ( :SFUN-*)&$7F) XOR $40 ) 


A683 




SYN 


:OR 


A683 +02 




DB 


:OR 


A684 




SYN 


JS , : SVAR 


A684 +CB 




DB 


$80+( ( ( :SVAR-*)&$7F) XOR $40 ) 


A685 




SYN 


:OR 


A685 +02 




DB 


:OR 


A686 




SYN 


:ESRT,AD, :TSCON-l 


A686 +01 




DB 


:ESRT 


A687 +27A4 




DW 


( :TSCON-l) 


A689 




SYN 


:RTN 


A689 +03 




DB 


:RTN 


<SFUN> = 


SFNP<NFP># 




A68A 




:3FUN SYN 


:ANTV, AD, :SFNP-1 


A68A +00 




DB 


:ANTV 


A68B +D5A7 




DW 


( :SFNP-1) 


A68D 




SYN 


JS, :NFP 


A68D +A5 




DB 


$80+( ( ( :NFP-*)&$7F) XOR $40 ) 


A68E 




SYN 


:RTN 


A68E +03 




DB 


:RTN 


< SVAR > = 


< TSVAR 


><SMAT># 




A68F 




:SVAR SYN 


:ESRT,AD, :TSVAR-1 


A68F +01 




DB 


:ESRT 


A690 +2DA3 




DW 


( :TSVAR-1) 


A692 




SYN 


JS , : SMAT 


A692 +C2 




DB 


$80+( ( ( :SMAT-*)&$7F) XOR $40 ) 


A693 




SYN 


:RTN 


A693 +03 




DB 


:RTN 



<SMAT> = ( <EXP> <SMAT2> 



&# 



A694 

A694 +2B 
A695 +0F 
A696 +37 



:SMAT SYN CLPRN. : CHNG, CSLPRN 

DB CLPRN 

DB :CHNG 

DB CSLPRN 



165 



Source Code 



A697 




SYN 


:VEXP 






A697 


+0E 


DB 


:VEXP 






A698 




SYN 


JS, :SMAT2 






A698 


+C4 


DB 


$80+ ( ( ( :SMAT2-* 


)&$7F) XOR $40 ) 


A699 




SYN 


CRPRN 






A699 


+ 2C 


DB 


CRPRN 






A69A 




SYN 


:0R 






A69A 


+02 


DB 


:0R 






A69B 




SYN 


:RTN 






A69B 


+03 


DB 


:RTN 






<SMAT2> 


= , <EXP> | &# 








A69C 




:SMAT2 SYN 


CCOM, :CHNG 


, CACOM 




A69C 


+ 12 


DB 


CCOM 






A69D 


+0F 


DB 


:CHNG 






A69E 


+3C 


DB 


CACOM 






A69F 




SYN 


:VEXP 






A69F 


+0E 


DB 


:VEXP 






A6A0 




SYN 


:OR 






A6A0 


+02 


DB 


:0R 






A6A1 




SYN 


:RTN 






A6A1 


+03 


DB 


:RTN 






<SOP> = 


< ><# 








A6A2 




:SOP 








A6A2 




SYN 


CLE, :CHNG,CSLE, 


:OR 




A6A2 


+1D 


DB 


CLE 






A6A3 


+0F 


DB 


:CHNG 






A6A4 


+2F 


DB 


CSLE 






A6A5 


+02 


DB 


:0R 






A6A6 




SYN 


CNE, :CHNG,CSNE, 


:OR 




A6A6 


+1E 


DB 


CNE 






A6A7 


+0F 


DB 


:CHNG 






A6A8 


+30 


DB 


CSNE 






A6A9 


+02 


DB 


:OR 






A6AA 




SYN 


CGE, :CHNG,CSGE, 


:OR 




A6AA 


+1F 


DB 


CGE 






A6AB 


+0F 


DB 


:CHNG 






A6AC 


+31 


DB 


CSGE 






A6AD 


+02 


DB 


:OR 






A6AE 




SYN 


CLT, :CHNG,CSLT, 


:OR 




A6AE 


+ 20 


DB 


CLT 






A6AF 


+0F 


DB 


:CHNG 






A6B0 


+3 2 


DB 


CSLT 






A6B1 


+02 


DB 


:OR 






A6B2 




SYN 


CGT, :CHNG,CSGT, 


:OR 




A6B2 


+21 


DB 


CGT 






A6B3 


+0F 


DB 


:CHNG 






A6B4 


+3 3 


DB 


CSGT 






A6B5 


+02 


DB 


:OR 






A6B6 




SYN 


CEQ, :CHNG,CSEQ 






A6B6 


+22 


DB 


CEO 






A6B7 


+ 0F 


DB 


:CHNG 






A6B8 


+34 


DB 


CSEO 






A6B9 




SYN 


:RTN 






A6B9 


+03 


DB 


:RTN 






<PUT> = 


<D1>,<EXP><EOS># 






A6BA 




:SPUT 








A6BA 




SYN 


CPND, :VEXP 






A6BA 


+1C 


DB 


CPND 






A6BB 


+0E 


DB 


:VEXP 






A6BC 




SYN 


CCOM 






A6BC 


+12 


DB 


CCOM 







166 



Source Code 



< > = <EXP><EOS># 



A6BD 




STRAP 




A6BD 




SGOTO 




A6BD 




SGOSUB 




A6BD 




SGR 




A6BD 




SCOLOR 




A6BD 




XEOS SYN 


:VEXP 


A6BD 


+0E 


DB 


:VEXP 


< > 


= <EOS># 






A6BE 




SCSAVE 




A6BE 




SCLOAD 




A6BE 




SDOS 




A6BE 




SCLR 




A6BE 




SRET 




A6BE 




SEND 




A6BE 




SSTOP 




A6BE 




SPOP 




A6BE 




SNEW 




A6BE 




SBYE 




A6BE 




SCONT 




A6BE 




SDEG 




A6BE 




SRAD 




A6BE 




SYN 


JS, :EOS 


A6BE 


+FA 


DB 


$80+( ( ( sEO 


A6BF 




SYN 


:RTN 


A6BF 


+03 


DB 


:RTN 



<LET> = <NVAR> =<EXP><EOS> <SVAR> = <STR>< EOS># 



A6C0 




:SLET 




A6C0 




:SILET 




A6C0 




SYN 


:ANTV, AD, :NVAR-1 


A6C0 


+00 


DB 


:ANTV 


A6C1 


+4BA6 


DW 


( :NVAR-1) 


A6C3 




SYN 


CEQ, :CHNG,CAASN 


A6C3 


+22 


DB 


CEQ 


A6C4 


+0F 


DP, 


:CHNG 


A6C5 


+2D 


DB 


CAASN 


A6C6 




SYN 


:VEXP 


A6C6 


+0E 


DB 


:VEXP 


A6C7 




SYN 


JS, :EOS 


A6C7 


+F1 


DB 


580+( ( ( :EOS-*)&$7F) XOR 540 ) 


A6C8 




SYN 


:OR 


A6C8 


+02 


DB 


:OR 


A6C9 




SYN 


JS, :SVAR 


A6C9 


+86 


DB 


?80+( ( ( :SVAR-*)&$7F) XOR $40 ) 


A6CA 




SYN 


CEQ, :CHNG,CSASN 


A6CA 


+22 


DB 


CEQ 


A6CB 


+0F 


DB 


:CHNG 


A6CC 


+2E 


DB 


CSASN 


A6CD 




SYN 


: ANTV, AD, : STR-1 


A6CD 


+00 


DB 


:ANTV 


A6CE 


+81A6 


DW 


( :STR-1 ) 


A6D0 




SYN 


JS, :EOS 


A6D0 


+E8 


DB 


$80+ ( ( ( :EOS-*)&$7F) XOR $40 ) 


A6D1 




SYN 


:RTN 


A6D1 


+03 


DB 


:RTN 


<FOR> = < 


TNVAR> = <EXP> 


TO <EXPxFSTEPxEOS># 


A6D2 




:SFOR SYN : ESRT, AD, :TNVAR-1 


A6D2 


+01 


DB 


:ESRT 


A6D3 


+2 9A3 


DW 


( :TNVAR-1 ) 


A6D5 




SYN 


CEQ, :CHNG, CAASN 


A6D5 


+22 


DB 


CEQ 


A6D6 


+0F 


DB 


:CHNG 


A6D7 


+2D 


DB 


CAASN 



167 



Source Code 



A6D8 






SYN 


:VEXP 


A6D8 


+0E 




DB 


:VEXP 


A6D9 






SYN 


CTO 


A6D9 


+19 




DB 


CTO 


A6DA 






SYN 


:VEXP 


A6DA 


+0E 




DB 


:VEXP 


A6DB 






SYN 


JS, :FSTEP 


A6DB 


+C3 




DB 


$80+( ( ( :FSTEP-*)6,$7F) XOR 540 ) 


A6DC 






SYN 


JS, :EOS 


A6DC 


+DC 




DB 


$80+( ( ( :E0S-*)&$7F) XOR $40 ) 


A6DD 






SYN 


:RTN 


A6DD 


+03 




DB 


:RTN 


<FSTEP> 


= STEP<EXP> | & 




A6DE 






:FSTEP 




A6DE 






SYN 


CSTEP 


A6DE 


+1A 




DB 


CSTEP 


A6DP 






SYN 


:VEXP 


A6DF 


+0E 




DB 


:VEXP 


A6E0 






SYN 


:0R 


A6E0 


+02 




DB 


:OR 


A6E1 






SYN 


:RTN 


A6E1 


+03 




DB 


:RTN 


< LOCATE 


> = <EXP>,<EXP>, 


,<TNVAR><EOL># 


A6E2 






: SLOCATE 




A6E2 






SYN 


:VEXP 


A6E2 


+0E 




DB 


:VEXP 


A6E3 






SYN 


CCOM 


A6E3 


+12 




DB 


CCOM 


A6E4 






SYN 


:VEXP 


A6E4 


+0E 




DB 


:VEXP 


A6E5 






SYN 


CCOM 


A6E5 


+12 




DB 


CCOM 


A6E6 






SYN 


JS, :SNEXT 


A6E6 


+C4 




DB 


$80+( ( t :SNEXT-*)&?7F) XOR $40 ) 


A6E7 






SYN 


:RTN 


A6E7 


+03 




DB 


:RTN 


<GET> = 


<D1>, 


<TNVAR># 




A6E8 






:SGET 




A6E8 






SYN 


JS, :D1 


A6E8 


+DD 




DB 


$80+( ( ( :D1-*)S$7F) XOR $40 ) 


A6E9 






SYN 


CCOM 


A6E9 


+12 




DB 


CCOM 



<NEXT> = <TNVAR><EOS># 



A6EA 




:SNEXT SYN 


:ESRT, AD, 


:TNVAR-1 




A6EA 


+01 


DB 


:ESRT 






A6EB 


+2 9A3 


DW 


( :TNVAR-1) 






A6ED 




SYN 


JS , : EOS 






A6ED 


+CB 


DB 


$80+( ( ( :EOS-*: 


&$7F) XOR 


$40 ) 


A6EE 




SYN 


:RTN 






A6EE 


+03 


DB 


:RTN 






< RESTORE > = 


= <EXP><EOS> | 


<EOS># 






A6EF 




:SREST SYN 


:VEXP 






A6EF 


+0E 


DB 


: VEXP 






A6F0 




SYN 


JS, :EOS 






A6F0 


+C8 


DB 


$80+( ( ( :EOS-* 


|&$7F) XOR 


$40 ) 


A6F1 




SYN 


:OR 






A6F1 


+02 


DB 


:OR 






A6F2 




SYN 


JS , : EOS 






A6F2 


+C6 


DB 


$80+( ( ( :EOS-* 


)&$7F) XOR 


$40 ) 


A6F3 




SYN 


:RTN 






A6F3 


+03 


DB 


:RTN 







168 



Source Code 



<INPUT> = <OPD><READ># 

A6F4 :SINPUT SYN 

A6F4 +P8 DB 

<READ> = <NSVARL> <EOS># 



JS, :OPD 
$80+( ( ( :0PD-*)&$7F) XOR $40 ) 



A6F5 

A6F5 +DB 
A6F6 

A6F6 +C2 
A6F7 
A6F7 +03 

EOS = : | CR# 

A6F8 

A6F8 +14 
A6F9 

A6F9 +02 
A6FA 

A6FA +16 
A6FB 
A6FB +03 



A6FC 
A6FC 
A6FC +C9 
A6FD 
A6FD +BB 
A6FE 

A6FE +02 
A6FF 

A6FF +ED 
A700 
A700 

A700 +00 
A701 +9FA7 
A703 

A703 +B5 
A704 
A704 +03 



:SREAD SYN JS , :NSVRL 

DB 580+ ( ( ( :NSVRL-*)&$7F) XOR $40 ) 
SYN JS, :EOS 

DB $80+( ( ( :EOS-*)&$7F) XOR $40 ) 
SYN : RTN 
DB :RTN 



:EOS SYN 


CEOS 




DB 




CEOS 




SYN 




:OR 




DB 




:OR 




SYN 




CCR 




DB 




CCR 




SYN 




:RTN 




DB 




:RTN 




;EOS> | 


<D1xPR1><EOS> 




:SPRINT 








SYN 




JS, :D1 




DB 




$80+( ( ( :D1-*)&$7F) XOR $40 ) 




SYN 




JS, :EOS 




DB 




$80+( ( ( :EOS-*)s,$7F) XOR $40 


) 


SYN 




:OR 




DB 




:OR 




SYN 




JS, :OPD 




DB 




$80+( ( ( :OPD-*)&$7F) XOR $40 


) 


:SLPRINT 








SYN 




:ANTV,AD, :PR1-1 




DB 




:ANTV 




DW 




( :PR1-1) 




SYN 




JS, :EOS 




DB 




$80+((( :EOS-*)£,$7F) XOR $40 


) 


SYN 




:RTN 




DB 




:RTN 





<D1> = <CPNDxEXP># 

: Dl 



A705 
A705 +1C 
A706 

A706 +0E 
A707 
A707 +0 3 



SYN CPND 

DB CPND 
SYN :VEXP 

DB :VEXP 
SYN :RTN 

DB : RTN 



<NSVAR> = <NVAR> | <SVAR># 



A708 
A708 +01 
A709 +29A3 
A70B 

A70B +02 
A70C 
A70C +01 
A70D +2DA3 
A70F 
A70F +03 



:NSVAR SYN 

DB 

DW 
SYN 

DB 
SYN 

DB 

DW 
SYN 

DB 



:ESRT,AD, :TNVAR-1 
:ESRT 
( :TNVAR-1 ) 

:OR 
:OR 

:ESRT, AD, :TSVAR-1 
:ESRT 
( :TSVAR-1) 

:RTN 
:RTN 



<NSVRL> = <NSVAR><NSV2> | &# 



A710 

A710 +B8 
A711 



:NSVRL SYN JS , : NSVAR 

DB $80+( ( ( :NSVAR-*)&$7F) XOR $40 ) 
SYN JS, :NSV2 



169 



Source Code 



A711 +C3 




DB 


$80+( ( ( :NSV2-*)S,$7F) XOR $40 ) 


A712 




SYN 


:OR, :RTN 


A712 +02 




DB 


:0R 


A713 +03 




DB 


:RTN 


<NSV2> 


= ,<NSVRL> | &# 




A714 




:NSV2 SYN CCOM 


A714 +12 




DB 


CCOM 


A715 




SYN 


JS, :NSVRL 


A715 +BB 




DB 


$80+( ( ( :NSVRL-*)&$7F) XOR $40 ) 


A716 




SYN 


:OR, :RTN 


A716 +02 




DB 


:OR 


A717 +03 




DB 


:RTN 


<XIO> = 


<AEXP> 


, <D2S> < 


FS>,<AEXP><EOS># 


A718 




:SX10 




A718 




SYN 


:VEXP 


A718 +0E 




DB 


:VEXP 


A719 




SYN 


CCOM 


A719 +12 




DB 


CCOM 


<OPEN> 


= <D1>, 


<EXP>,< 


EXP>,<FS>,<EOS># 


A71A 




:SOPEN 




A71A 




SYN 


JS, :D1 


A71A +AB 




DB 


$80+( ( ( :D1-*)S$7F) XOR $40 ) 


A71B 




SYN 


CCOM 


A71B +12 




DB 


CCOM 


A71C 




SYN 


JS, :TEXP 


A71C +F9 




DB 


$80+( ( ( :TEXP-*)S,$7F) XOR $40 ) 


A71D 




SYN 


CCOM 


A71D +12 




DB 


CCOM 


A71E 




SYN 


JS, :FS 


A71E +F3 




DB 


$80+(((:FS-*)&$7F) XOR $40 ) 


A71F 




SYN 


JS, :EOS 


A71F +99 




DB 


$80+( ( ( :EOS-*)&$7F) XOR $40 ) 


A720 




SYN 


:RTN 


A720 +03 




DB 


:RTN 


< CLOSE > 


= <D1xEOS># 




A721 




:SCLOSE 




A721 




SYN 


JS, :D1 


A721 +A4 




DB 


$80+( ( ( :D1-*)&$7F) XOR $40 ) 


A722 




SYN 


JS, :EOS 


A722 +96 




DB 


$80+( ( ( :EOS-*)&$7F) XOR $40 ) 


A723 




SYN 


:RTN 


A723 +03 




DB 


:RTN 


< > = <FS><EOS># 




A724 




: SENTER 




A724 




:SLOAD 




A724 




:SSAVE 




A724 




SYN 


JS, :FS 


A724 +ED 




DB 


$80+( ( ( :FS-*)i$7F) XOR $40 ) 


A725 




SYN 


JS, :EOS 


A725 +93 




DB 


$80+( ( ( :EOS-*)&$7F) XOR $40 ) 


A726 




SYN 


:RTN 


A726 +03 




DB 


:RTN 


<RUN> = 


<FS><EOS2> <EOS2># 


A727 




:SRUN 




A727 




SYN 


JS, :FS 


A727 +EA 




DB 


$80+( ( ( :FS-*)&$7F) XOR $40 ) 


A728 




SYN 


JS, :EOS 


A728 +90 




DB 


$80+( ( ( :EOS-*)£,$7F) XOR $40 ) 


A729 




SYN 


■ OR 


A729 +02 




DB 


:OR 



170 



Source Code 



A72A 






SYN 


JS, :E0S 


A72A 


+8E 




DB 


$80+( ( (:E0S-*)&$7F) XOR $40 ) 


A72B 






SYN 


:RTN 


A72B 


+03 




DB 


:RTN 


<OPD> = < 


D1 


>, | # 




A72C 






:0PD 




A72C 






SYN 


JS, :D1 


A72C 


+99 




DB 


$80+(( (:D1-*)&S7F) XOR $40 ) 


A72D 






:0PDX SYN 


CCOM 


A72D 


+ 12 




DB 


CCOM 


A72E 






SYN 


:0R 


A72E 


+02 




DB 


:0R 


A72F 






SYN 


JS, :D1 


A72F 


+96 




DB 


$80+( (( :D1-*)6,$7F) XOR $40 ) 


A730 






SYN 


CSC 


A730 


+ 15 




DB 


CSC 


A731 






SYN 


:0R 


A731 


+02 




DB 


:0R 


A732 






SYN 


:RTN 


A732 


+03 




DB 


:RTN 


<UST> = < 


FS>;<L2> ! <L2># 


i 


A733 






:SL1ST 




A733 






SYN 


JS, :FS 


A733 


+DE 




DB 


$80+( ( ( :FS-*)6,$7F) XOR $40 ) 


A734 






SYN 


JS, :EOS 


A734 


+84 




DB 


$80+( ( ( :E0S-*)&$7F) XOR $40 ) 


A735 






SYN 


:0R 


A735 


+02 




DB 


:0R 


A736 






SYN 


JS , : FS 


A736 


+DB 




DB 


$80+( ( ( :FS-*)E,$7F) XOR $40 ) 


A737 






SYN 


CCOM 


A737 


+ 12 




DB 


CCOM 


A738 






SYN 


JS, :LIS 


A738 


+C4 




DB 


$80+( ( t :LIS-*)&$7F) XOR $40 ) 


A739 






SYN 


:0R 


A739 


+02 




DB 


:0R 


A73A 






SYN 


JS, :LIS 


A73A 


+C2 




DB 


$80+( ( ( :LIS-*)&$7F) XOR $40 ) 


A73B 






SYN 


:RTN 


A73B 


+03 




DB 


:RTN 


<LIS> = <L1> 


<EOS2># 




A73C 






:LIS 




A73C 






SYN 


:ANTV,AD, :L1-1 


A73C 


+00 




DB 


:ANTV 


A73D 


+BFA7 




DW 


(:L1-1) 


A73F 






SYN 


JS, :EOS2 


A73F 


+F4 




DB 


$80+(( ( :EOS2-*)6,$7F) XOR $40 ) 


A740 






SYN 


:RTN 


A740 


+03 




DB 


:RTN 


< STATUS > = 


= < 


STATxEOS2># 




A741 






:SSTATUS 




A741 






SYN 


JS, :STAT 


A741 


+C3 




DB 


$80+ ( ( C :STAT-*)&$7F) XOR $40 ) 


A742 






SYN 


JS, :EOS2 


A742 


+F1 




DB 


$80+( ( ( :EOS2-*)&$7F) XOR $40 ) 


A743 






SYN 


:RTN 


A743 


+03 




DB 


:RTN 


<STAT> = < 


01 


> , < NVAR > # 




A744 






:STAT 




A744 






SYN 


JS, :D1 


A744 


+81 




DB 


$80+( ( ( :D1-*)&$7F) XOR $40 ) 



171 



Source Code 



A745 


SYN 


CCOM 




A745 +12 


DB 


CCOM 




A746 


SYN 


:ANTV,AD, :NVAR-1 




A746 +00 


DB 


: ANTV 




A747 +4BA6 


DW 


( :NVAR-1 ) 




A749 


SYN 


:RTN 




A749 +03 


DB 


:RTN 




< > =<STAT>,<NVARxEOS2># 




A74A 


:SNOTE 






A74A 


:SPOINT 






A74A 


SYN 


JS, :STAT 




A74A +BA 


DB 


$80+(( ( :STAT-*)&$7F) XOR 


$40 ) 


A74B 


SYN 


CCOM 




A74B +12 


DB 


CCOM 




A74C 


SYN 


: ANTV, AD, :NVAR-1 




A74C +00 


DB 


:ANTV 




A74D +4BA6 


DW 


( tNVAR-1) 




A74F 


SYN 


JS, :EOS2 




A74F +E4 


DB 


$80+( ( ( :EOS2-*)s,$7F) XOR 


$40 ) 


A750 


SYN 


:RTN 




A750 +03 


DB 


:RTN 




<FS> = <STR> 








A751 


:FS 






A751 


SYN 


:ANTV,AD, :STR-1 




A751 +00 


DB 


:ANTV 




A752 +81A6 


DW 


( :STR-1) 




A754 


SYN 


:RTN 




A754 +03 


DB 


:RTN 




<TEXP> = <EXP>,<EXP># 






A755 


TEXP 






A755 


SYN 


:VEXP 




A755 +0E 


DB 


:VEXP 




A756 


SYN 


CCOM 




A756 +12 


DB 


CCOM 




A757 


SYN 


:VEXP 




A7S7 +0E 


DB 


:VEXP 




A758 


SYN 


:RTN 




A758 +03 


DB 


:RTN 




<SOUND> = <EXP>,<EXP>, 


<EXP>,<EXPxEOS># 




A759 


SSOUND 






A759 


SYN 


:VEXP 




A759 +0E 


DB 


: VEXP 




A75A 


SYN 


CCOM 




A75A +12 


DB 


CCOM 




A75B 


tSSETCOLOF 






A75B 


SYN 


:VEXP 




A75B +0E 


DB 


:VEXP 




A75C 


SYN 


CCOM 




A75C +12 


DB 


CCOM 




< > =<EXP>,<EXP><EOS># 




A75D 


SPOKE 






A75D 


SPLOT 






A75D 


SPOS 






A75D 


SDRAWTO 






A75D 


SYN 


JS, :TEXP 




A75D +B8 


DB 


$80+( ( ( :TEXP-*)&$7F) XOR 


$40 ) 


A75E 


SYN 


JS, :EOS2 




A75E +D5 


DB 


$80+( ( ( :EOS2-*)S,$7F) XOR 


$40 ) 


A75F 


SYN 


:RTN 




A75F +03 


DB 


: RTN 





172 



Source Code 



<DIM> = <NSML> <EOS># 



A760 




:SDIM 


A760 
A760 




:SCOM 

SYN 


A760 


+EC 


DB 


A761 




SYN 


A761 


+D2 


DB 


A762 




SYN 


A762 


+03 


Dl 



JS, :NSML 
$80+( ( ( :NSML-*)S,$7F) XOR $40 ) 

JS, :E0S2 
$B0+( ( ( :EOS2-*)5,$7F) XOR $40 ) 

:RTN 
:RTN 



<ON> = <EXP> <ON1><EXPLxEOS># 



A763 




:SON SYN 


:VEXP 


A763 +0E 




DB 


:VEXP 


A764 




SYN 


JS, :0N1 


A764 +C4 




DB 


$80+( ( ( :ONl-*)£,$7F) XOR $40 ) 


A765 




SYN 


JS, :EXPL 


A765 +C7 




DB 


$80+( ( ( :EXPL-*)S-$7F) XOR $40 ) 


A766 




SYN 


JS, :EOS2 


A766 +CD 




DB 


$80+( ( ( :EOS2-*)&$7F) XOR $40 ) 


A767 




SYN 


:RTN 


A767 +03 




DB 


:RTN 


<ON1> = 


GOTO 


GOSUB# 




A76S 




:ONl SYN 


CGTO 


A768 +17 




DB 


CGTO 


A769 




SYN 


:OR 


A769 +02 




DB 


:OR 


A76A 




SYN 


CGS 


A76A +18 




DB 


CGS 


A76B 




SYN 


:RTN 


A76B +03 




DB 


:RTN 


<EXPL> = 


<EXPxEXPL1># 




A76C 




:EXPL SYN 


:VEXP 


A76C +0E 




DB 


:VEXP 


A76D 




SYN 


JS, :EXPL1 


A76D +C2 




DB 


$80+( ( ( :EXPL1-*)&$7F) XOR $40 


A76E 




SYN 


:RTN 


A76E +03 




DB 


:RTN 


<EXPL1> 


= ,<EXPL> | &# 




A76F 




:EXPL1 SYN 


CCOM 


A76F +12 




DB 


CCOM 


A770 




SYN 


JS, :EXPL 


A770 +BC 




DB 


$80+( ( ( :EXPL-*)£,$7F) XOR $40 ) 


A771 




SYN 


:OR 


A771 +02 




DB 


:OR 


A772 




SYN 


:RTN 


A772 +03 




DB 


:RTN 


<EOS2> = 


=CEOS | CCR# 




A773 




:E0S2 




A773 




SYN 


CEOS 


A773 +14 




DB 


CEOS 


A774 




SYN 


:OR 


A774 +02 




DB 


:OR 


A775 




SYN 


CCR 


A775 +16 




DB 


CCR 


A776 




SYN 


:RTN 


A776 +03 




DB 


:RTN 


<NSMAT> = <TNVAR> ( <EXP> <NMAT2> ) 


A777 




: NSMAT 




A777 




SYN 


:ESRT, AD, :TNVAR-1 


A777 +01 




DB 


:ESRT 



173 



Source Code 



A778 


+29A3 




DW 


( :TNVAR-1) 


A77A 






SYN 


CLPRN, :CHNG,CDLPRN 


A77A 


+2B 




DB 


CLPRN 


A77B 


+0F 




DB 


:CHNG 


A77C 


+39 




DB 


CDLPRN 


A77D 






SYN 


:VEXP 


A77D 


+0E 




DB 


:VEXP 


A77E 






SYN 


:ANTV,AD, :NMAT2-1 


A77E 


+00 




DB 


:ANTV 


A77F 


+ 58A6 




DW 


( :NMAT2-1) 


A781 






SYN 


CRPRN 


A781 


+2C 




DB 


CRPRN 


A782 






SYN 


:0R 


A782 


+02 




DB 


:OR 


A783 






SYN 


:ESRT, AD, :TSVAR-1 


A783 


+01 




DB 


:ESRT 


A784 


+2DA3 




DW 


( :TSVAR-1) 


A786 






SYN 


CLPRN, :CHNG,CDSLPR 


A786 


+2B 




DB 


CLPRN 


A787 


+0F 




DB 


:CHNG 


A788 


+3B 




DB 


CDSLPR 


A789 






SYN 


:VEXP 


A789 


+0E 




DB 


:VEXP 


A78A 






SYN 


CRPRN 


A78A 


+2C 




DB 


CRPRN 


A78B 






SYN 


:RTN 


A78B 


+03 




DB 


:RTN 


<NSML> = 


<NSMAT> 


<NSML2 


> | &# 


A78C 




:NSML SYN 


JS, :NSMAT 


A78C 


+AB 




DB 


$80+(( ( :NSMAT-*)&$7F) XOR $40 ) 


A78D 






SYN 


JS, :NSML2 


A78D 


+C3 




DB 


$80+( ( ( :NSML2-*)E,$7F) XOR $40 ) 


A78E 






SYN 


:OR, :RTN 


A78E 


+02 




DB 


:OR 


A78F 


+03 




DB 


:RTN 


<NSML2> = 


= ,<NSML> 


| &# 




A790 




:NSML2 SYN 


CCOM 


A790 


+ 12 




DB 


CCOM 


A791 






SYN 


JS, :NSML 


A791 


+BB 




DB 


$80+( ( ( :NSML-*)&$7F) XOR $40 ) 


A792 






SYN 


:OR, :RTN 


A792 


+02 




DB 


:OR 


A793 


+03 




DB 


:RTN 


<IF> 


= <EXP> THEN < 


IFA><EOS># 


A794 




:SIF SYN 


: VEXP 


A794 


+0E 




DB 


:VEXP 


A795 






SYN 


CTHEN 


A795 


+1B 




DB 


CTHEN 


A796 






SYN 


JS, :IFA 


A796 


+C3 




DB 


$80+( ( ( :IFA-*)S,$7F) XOR $40 ) 


A797 






SYN 


JS, :EOS2 


A797 


+9C 




DB 


$80+( ( ( :EOS2-*)6,$7F) XOR $40 ) 


A798 






SYN 


:RTN 


A798 


+03 




DB 


:RTN 



<IFA> = <TNCON> I <EIF> 



A799 

A799 +01 
A79A +FFA3 
A79C 

A79C +02 
A79D 
A79D +01 
A79E +D3A2 



:ESRT, AD, :TNCON-l 



DB 


:ESRT 


DW 


( :TNCON-l ) 


SYN 


:OR 


DB 


:OR 


SYN 


:ESRT, AD, :EIF 


DB 


:ESRT 


DW 


( :EIF-1) 



174 



Source Code 



<PR1> = <PEL> I <PSL><PR2> | &# 

:PR1 



A7A0 
A7A0 

A7A0 +C9 
A7A1 +02 
A7A2 

A7A2 +D4 
A7A3 

A7A3 +C3 
A7A4 

A7A4 +02 
A7A5 
A7A5 +03 



SYN JS, :PEL, :OR 

DB $80+( ( ( :PEL-*)&$7F) XOR $40 ) 

DB :OR 

SYN JS, :PSL 

DB $80+( ( ( :PSL-*)5.$7F) XOR $40 ) 

SYN JS, :PR2 

DB $80+( ( ( :PR2-*)&$7F) XOR $40 ) 

SYN :OR 

DB :OR 

SYN : RTN 

DB : RTN 



<PR2> = <PEL> &# 

A7A6 :PR2 

A7A6 +C3 

A7A7 

A7A7 +02 

A7A8 

A7A8 +03 

<PEL> = <PES> <PELA># 

: PEL 





3YN 


JS, 


:PEL 


DB 




?80+(((: 


:PEL-*)&$7F) XOR $40 ) 


SYN 




:OR 




DB 




:OR 




SYN 




:RTN 




DB 




:RTN 





A7A9 
A7A9 +C3 
A7AA 

A7AA +C8 
A7AB 
A7AB +03 



SYN JS, :PES 
DB $80+( ( ( :PES-*)s,$7F) XOR $40 ) 
SYN JS, :PELA 

DB $80+( ( ( :PELA-*)&$7F) XOR $40 ) 
SYN : RTN 
DB : RTN 



<PES> = <EXP> I <STR> 



A7AC 






:PES SYN 


:VEXP 


A7AC 


+0E 




DB 


: VEXP 


A7AD 






SYN 


:OR 


A7AD 


+02 




DB 


:OR 


A7AE 






SYN 


: ANTV, AD, : STR-1 


A7AE 


+00 




DB 


:ANTV 


A7AF 


+81A6 




DW 


( : STR-1 ) 


A7B1 






SYN 


:RTN 


A7B1 


+03 




DB 


:RTN 


<PELA> = < 


PSL> < 


PEL> j &# 




A7B2 






:PELA SYN 


JS, :PSL 


A7B2 


+C4 




DB 


$80+( ( ( :PSL-*)&$7F) XOR $40 ) 


A7B3 






SYN 


JS, :PR2 


A7B3 


+B3 




DB 


$80+( ( ( :PR2-*)6,$7F) XOR $40 ) 


A7B4 






SYN 


:OR 


A7B4 


+02 




DB 


:OR 


A7B5 






SYN 


:RTN 


A7B5 


+03 




DB 


:RTN 



<PSL> = <PS> <PSLA># 



A7B6 

A7B6 +C6 
A7B7 

A7B7 +C2 
A7B8 
A7B8 +03 



A7B9 

A7B9 +BD 
A7BA 



L SYN JS, :PS 

DB $80+( ( ( :PS-*)&$7F) XOR $40 ) 
SYN JS, :PSLA 

DB $80+( ( ( :PSLA-*)&$7F) XOR $40 ) 
SYN : RTN 

DB : RTN 



<PSLA> = <PSL> [ &# 



:PSLA SYN JS, :PSL 

DB $80+( ( (:PSL-*)6,$7F) XOR $40 ) 
SYN :OR 



175 



Source Code 



A7BA 


+02 


A7BB 




A7BB 


+03 


<PS>=, 


A7BC 




A7BC 


+12 


A7BD 




A7BD 


+02 


A7BE 




A7BE 


+15 


A7BF 




A7BP 


+03 


< L1 > = < 


A7C0 




A7C0 


+0E 


A7C1 




A7C1 


+C3 


A7C2 




A7C2 


+02 


A7C3 




A7C3 


+03 



,# 



DB 


:0R 


SYN 


:RTN 


DB 


:RTN 



DB 


CCOM 


SYN 


:0R 


DB 


:0R 


SYN 


CSC 


DB 


CSC 


SYN 


:RTN 


DB 

U 4t 


:RTN 


SYN 


:VEXP 


DB 


:VEXP 


SYN 


JS, :L2 


DB 


$80+(((:L2 


SYN 


:OR 


DB 


:0R 


SYN 


:RTN 


DB 


:RTN 



L2-*)&$7F) XOR ?40 ) 



<L2> =,<EXP> | &# 



A7C4 :L2 SYN CC 

A7C4 +12 DB CCOM 

A7C5 SYN :VEXP 

A7C5 +0E DB :VEXP 

A7C6 SYN :OR 

A7C6 +02 DB :OR 

A7C7 SYN :RTN 

A7C7 +03 DB :RTN 

<REM> = <EREM> 



A7C8 
A7C8 +01 
A7C9 +DPA2 



:SREM SYN 

DB :ESRT 

DW ( : EREM-1 ) 



ESRT.AD, :EREM-1 



<SDATA> = <EDATA> 

A7CB 
A7CB +01 
A7CC +DFA2 



:SDATA SYN 

DB :ESRT 

DW ( : EDATA-1 ) 



:ESRT,AD, : EDATA-1 



<NFSP> =ASC | VAL | LEN# 



A7CE 
A7CE +40 
A7CF +02 
A7D0 

A7D0 +41 
A7D1 +02 
A7D2 

A7D2 +43 
A7D3 +02 
A7D4 
A7D4 +42 
A7D5 
A7D5 +03 



P SYN 


CASC, :OR 


DB 


CASC 


DB 


:OR 


SYN 


CVAL, :OR 


DB 


CVAL 


DB 


:OR 


SYN 


CADR, :OR 


DB 


CADR 


DB 


:OR 


SYN 


CLEN 


DB 


CLEN 


SYN 


:RTN 


DB 


:RTN 



176 



Source Code 



<SFNP> = STR | CHR# 



A7D6 

A7D6 +3D 
A7D7 +02 
A7D8 

A7D8 +3E 
A7D9 
A7D9 +03 



SFNP SYN 


CSTR, 


:OR 


DB 


CSTR 




DB 


:0R 




SYN 


CCHR 




DB 


CCHR 




SYN 


:RTN 




DB 


:RTN 





<PUSR> = <EXP> <PUSR1># 



A7DA 




PUSR SYN 


:VEXP 


A7DA +0E 






DB 


:VEXP 


A7DB 






SYN 


JS, :PUSR1 


A7DB +C2 






DB 


$80+( ( ( :PUSR1-*)&$7F) XOR $40 


A7DC 






SYN 


:RTN 


A7DC +03 






DB 


:RTN 


<PUSR1> = 


,<PUSR 


> 


| &# 




A7DD 




PUSR1 SYN 


CCOM, :CHNG,CACOM 


A7DD +12 






DB 


CCOM 


A7DE +0F 






DB 


:CHNG 


A7DF +3C 






DB 


CACOM 


A7E0 






SYN 


JS, :PUSR 


A7E0 +BA 






DB 


$80+(((:PUSR-*)6.$7F) XOR $40 ) 


A7E1 






SYN 


:OR 


A7E1 +02 






DB 


:OR 


A7E2 






SYN 


:RTN 


A7E2 +03 






DB 


:RTN 



OPNTAB — Operator Name Table 



A7E3 





= 000F 


C 




SET 




$0F 


A7E3 


= 0010 
= 0010 
82 


C 
CDQ 


DB 


SET 
EQU 


$82 


C+l 

C 


A7E4 


= 0011 
= 0011 
80 


C 
CSOE 

DB 


SET 
EQU 


$80 


C+l 
C 


A7E5 


= 0012 
» 0012 
AC 


C 
CCOM 

DC 


SET 
EQU 


. 


C+l 

c 


A7E6 


= 0013 
= 0013 
A4 


C 
CDOL 

DC 


SET 
EQU 

'$ 




C+l 

c 


A7E7 


= 0014 
= 0014 
BA 


C 
CEO£ 


DC 


SET 
EQU 


i 


C+l 

c 


A7E8 


= 0015 
= 0015 
BB 


C 
CSC 


DC 


SET 
EQU 


■ 


C+l 

c 


A7E9 


= 0016 
= 0016 
9B 


C 
CCR 


DB 


SET 
EQU 


CR 


C+l 

c 


A7EA 


■ 0017 
= 0017 
474F54CF 


C 
CGTC 


DC 


SET 
EQU 

'GOTO 


C+l 

c 



,-FIRST ENTRY VALUE=$10 



,- DOUBLE QUOTE 



DUMMY FOR SOE 



; CARRIAGE RETURN 



177 



Source Code 



A7F3 



A7F5 



A7FE 



A800 



A806 



A80C 



= 0018 
= 0018 
474F5355C2 


C 
CGS 


DC 


SET C+l 
EQU C 
'GOSUB' 


= 0019 
= 0019 
54CF 


c 

CTO 


DC 


SET 
EQU 

'TO' 


C + l 
C 


= 001A 
= 001A 
535445D0 


C 

CSTEP 
DC 


SET 
EQU 

'STEP 


C+l 

c 


= 001B 
= 001B 
544845CE 


C 
CTHF 


:N 
DC 


SET 
EQU 

'THEN 


C+l 
C 


= 001C 
= 001C 
A3 


C 

CPNC 


1 
DC 


SET 
EQU 

'#' 


C+l 

c 


= 001D 


CSROP 


EQU 


C+l 


= 001D 
= 001D 
3CBD 


C 
CLE 


DC 


SET 
EQU 
' <= ' 


C+l 
C 


= 001E 
= 001E 
3CBE 


C 
CNE 


DC 


SET 
EQU 
' <> ' 


C+l 
C 


= 001F 
= 001F 
3EBD 


C 
CGE 


DC 


SET 
EQU 
' >= ' 


C+l 
C 


= 0020 
= 0020 
BC 


C 
CLT 


DC 


SET 
EQU 
1 < ' 


C+l 

c 


= 0021 
= 0021 
BE 


C 
CGT 


DC 


SET 
EQU 
1 > ' 


C+l 

c 


= 0022 
= 0022 

BD 


C 
CEQ 


DC 


SET 
EQU 


C+l 

c 


= 0023 
= 0023 
DE 


C 
CEXP 

DB 


SET 
EQU 

$5E 


C+l 

c 

+ $80 


= 0024 
= 0024 
AA 


C 
CMUL 

DC 


SET 
EQU 


C+l 

c 


= 0025 
= 0025 
AB 


C 

CPLUS 
DC 


SET 
EQU 
'+ ' 


C+l 

c 


= 0026 
= 0026 
AD 


Q 

CMINUS 
DC 


SET 
EQU 


C+l 

c 


= 0027 
= 0027 
AF 


C 
CDIV 

DC 


SET 
EQU 

'/' 


C+l 

c 


= 0028 
= 0028 
4E4FD4 


C 
CNOT 

DC 


SET 
EQU 

'NOT' 


C+l 

c 



START OF REAL OPS 



;UP ARROW FOR EXP 



178 



Source Code 



A80F 


= 0029 
= 0029 
4FD2 


C 
COR 

DC 


SET 
EQU 
'OR' 


C+l 

c 


A811 


= 002A 
= 002A 
414EC4 


C 
CAND 

DC 


SET 
EQU 

'AND' 


C+l 

c 


A814 


■ 002B 
= 002B 
A8 


C 
CLPRN 

DC 


SET 
EQU 
'( ' 


C+l 

c 


A815 


= 002C 
= 002C 
A9 


C 

CRPRN 
DC 


SET 
EQU 
')' 


C + l 
C 



A816 



A817 



A818 



A81A 



A81C 



A81F 



A821 



A82 2 



A823 



THE FOLLOWING ENTRIES ARE COMPRISED OF CHARACTERS 
SIMILAR TO SOME OF THOSE ABOVE BUT HAVE 
DIFFERENT SYNTACTICAL OR SEMANTIC MEANING 



.-ARITHMETIC ASSIGMENT 



= 002D 
= 002D 
BD 


C 

CAASN 
DC 


SET 
EQU 


C + l 
C 


= 002E 
= 002E 
BD 


C 

CSASN 
DC 


SET 
EQU 


C+l 
C 


= 002F 
= 002F 
3CBD 


C 
CSLE 

DC 


SET 
EQU 


C + l 

c 


= 0030 
= 0030 
3CBE 


C 
CSNE 

DC 


SET 
EQU 
' <> ' 


C+l 

c 


= 0031 
= 0031 
3EBD 


C 
CSGE 

DC 


SET 
EQU 
' >= ' 


C+l 

c 


= 0032 
= 0032 
BC 


C 
CSLT 

DC 


SET 
EQU 
' < ' 


C+l 

c 


= 0033 
■ 0033 
BE 


C 
CSGT 

DC 


SET 
EQU 
' > ' 


C+l 

c 


= 0034 
= 0034 
BD 


C 
CSEQ 

DC 


SET 
EQU 


C+l 
C 


= 0035 
= 3035 
AB 


C 

CUPLUS 
DC 


SET 
EQU 
'+ ' 


C+l 

c 


= 0036 
= 0036 

AD 


C 

CUMINUS 
DC 


SET 
EQU 


C + l 

c 


= 0037 
= 0037 
A8 


C 

CSLPRN 
DC 


SET 
EQU 
'( ' 


C+l 

c 


= 0038 
= 0038 
80 

= 0039 
= 0039 


C 

CALPRN 
DB 
C 
CDLPRN 


SET 
EQU 

$80 
SET 

EQU 


C+l 
C 

C + l 

c 



STRING OPS 



; UNARY PLUS 



UNARY MINUS 



; STRING LEFT PAREN 



; ARRAY LEFT PAREN 
; DOES NOT PRINT 



DIM LEFT PAREN 



179 



Source Code 



A825 


80 


DB 




$80 




; DOES NOT PR 


A826 


= 003A 
= 003A 
A8 


C 

CPLPRN 
DC 


SET 
EQU 




C+l 
C 


; FUNCTION LE 


A827 


= 003B 
= 003B 
A8 


C 

CDSLPR 
DC 


SET 
EQU 
'( 


, 


C+l 

c 




A828 


= 003C 
= 003C 
AC 


C 

CACOM 
DC 


SET 
EQU 




C + l 
C 


I ARRAY COMMA 



Function Name Table 



PART OF ONTAB 





= 003D 


C 




SET C+l 




= 003D 


CFFUN 


EQU C 




= 003D 


CSTR 


EQU C 


A829 


535452A4 




DC 


'STR5 ' 




= 003E 


C 




SET C+l 




= 003E 


CCHR 


EQU C 


A82D 


434852A4 




DC 


'CHR$' 




= 003F 


C 




SET C+l 




= 003F 


CUSR 


EQU C 


A831 


5553D2 




DC 


'USR' 




= 0040 


C 




SET C+l 




= 0040 


CASC 


EQU C 


A834 


4153C3 




DC 


'ASC 




= 0041 


C 




SET C+l 




= 0041 


CVAL 


EQU C 


A837 


5641CC 




DC 


'VAL' 




= 0042 


C 




SET C+l 




= 0042 


CLEN 


EQU C 


A83A 


4C45CE 




DC 


'LEN' 




= 0043 


C 




SET C+l 




= 0043 


CADR 


EQU C 


A83D 


4144D2 




DC 


'ADR' 




= 0044 


C 




SET C+l 




= 0044 


CNFNP 


EQU C 


A840 


4154CE 




DC 


'ATN' 


A843 


434FD3 




DC 


'COS' 


A846 


504545CB 




DC 


'PEEK' 


A84A 


5349CE 




DC 


'SIN' 


A84D 


524EC4 




DC 


'ROT' 


A850 


4652C5 




DC 


'FRE' 


A853 


4558D0 




DC 


'EXP' 


A856 


4C4FC7 




DC 


'LOG' 


A859 


434C4FC7 




DC 


' CLOG ' 


A85D 


5351D2 




DC 


'SQR' 


A860 


S347CE 




DC 


'SGN' 


A863 


4142D3 




DC 


'ABS ' 


A866 


494ED4 




DC 


'INT' 


A869 


504144444C 
C5 




DC 


' PADDLE ' 


A86F 


53544943CB 




DC 


'STICK' 


A874 


50545249C7 




DC 


'PTRJG ' 


A879 


53545249C7 




DC 


'STRIG ' 


A87E 


00 




DB 


500 






; 


END OF OPNTAB S. FNTAB 



;FIRST FUNCTION CODE 



;USR FUNCTION CODE 



180 



Source Code 



Memory Manager 



A87F 



MEMORY MANAGEMENT CONSISTS OF EXPANDING AND 
CONTRACTING TO INFORMATION AREA POINTED TO 
BY THE ZERO PAGE POINTER TABLES. ROUTINES 
MODIFY THE ADDRESS IN THE TABLES AND 
MOVE DATA AS REQUIRED. THE TWO FUNDAMENTAL 
ROUTINES ARE 'EXPAND' AND 'CONTRACT' 



EXPAND 



X = ZERO PAGE ADDRESS OF TABLE AT WHICH 

EXPANSION IS TO START 

Y = EXPANSION SIZE IN BYTES [LOW] 

A = EXPANSION SIZE IN BYTES [HIGH] 



EXPLOW - FOR EXPANSION < 256 BYTES 
SETS A = 



A87F 


A900 


EXPLOW LDA 


#0 


A881 




EXPAND 




A881 


84A4 


STY 


ECSIZE 


A883 


85A5 


STA 


ECSIZE+1 


A885 


38 


SEC 




A886 


A590 


LDA 


MEM TOP 


A888 


65A4 


ADC 


ECSIZE 


A88A 


A8 


TAY 




A88B 


A591 


LDA 


MEMTOP+1 


A88D 


65A5 


ADC 


ECSIZE+1 


A88F 


CDE602 


CMP 


HIMEM+1 


A892 


900C "A8A0 


BCC 


:EXP2 


A894 


D007 "A89D 


BNE 


:EXP1 


A896 


CCE502 


CPY 


HIMEM 


A899 


9005 ~A8A0 


BCC 


:EXP2 


A89B 


F003 "A8A0 


BEQ 


:EXP2 


A89D 


4C3CB9 


:EXP1 JMP 


MEMFULL 


A8A0 




iEXP2 




A8A0 


38 


SEC 




A8A1 


A590 


LDA 


MEMTOP 


A8A3 


F500 


SBC 


0,X 


A8A5 


85A2 


STA 


MVLNG 


A8A7 


A591 


LDA 


MEMTOP+1 


A8A9 


F501 


SBC 


1,X 


A8AB 


85A3 


STA 


MVLNG+1 


A8AD 


18 


CLC 




A8AE 


7501 


ADC 


1,X 


A8B0 


859A 


STA 


MVFA+1 


A8B2 


B500 


LDA 


0,X 


A8B4 


8599 


STA 


MVFA 


A8B6 


8597 


STA 


SVESA 


A8B8 


65A4 


ADC 


ECSIZE 



A8BA 859B 



A8BC 


B501 


A8BE 


8598 


A8C0 


65A5 


A8C2 


6 5A3 


A8C4 


859C 



LDA 


1,X 


STA 


SVESA+1 


ADC 


ECSIZE+1 


ADC 


MVLNG+1 


STA 


MVTA+1 



SAVE EXPAND SIZE 

TEST MEMORY TO BE FULL 

MEMTOP+ECSIZE+1 

MUST BE LE 

HIMEM 



FORM MOVE LENGTH [MVLNG] 
MOVE FROM ADR [MVFA] 
MVLNG = MEMTOP-EXPAND ADR 

MVFA[L] = EXP ADR [L] 

MVFA[H] = EXP ADR[H] + 

MVLNG[H] 

DURING MOVE MVLNG[L] 

WILL BE ADDED SUCH 

THAT MVFA = MEMTOP 

SAVE PREMOVE EXPAND AT VALUE 

SET MVFA LOW 

FORM MOVE TO ADR [MVTA] 

MVTA[L] = EXP ADR[L] + 

ECSIZE[L] 

MVTA[H] = [CARRY + EXP 

AD-[H] 

+ECSIZE[H]] + MVLNG[H] 

DURING MOVE MVLNG[L] 
WILL BE ADDED SUCH THAT 
MVTA = MEMTOP + ECSIZE 



181 



Source Code 



A8C6 
A8C8 
A8CA 
A8CC 
A8CE 
A8D0 
A8D2 
A8D3 
A8D4 
A8D6 
A8D8 
A8DA 
A8DC 

A8DE 
A8E0 



B500 

65A4 

9500 

B501 

65A5 

9501 

E8 

E8 

E092 

90EE 

850F 

A590 

850E 

A6A3 
E8 



A8E1 A4A2 
A8E3 D00B 
A8E5 F010 



'A8F0 
'A8F7 



LDA 


0,X 


ADC 


ECSIZE 


STA 


0,X 


LDA 


1,X 


ADC 


ECSIZE+1 


STA 


1,X 


I NX 




I NX 




CPX 


#MEMTOP+2 


BCC 


:EXP3 


STA 


APHM+1 


LDA 


MEMTOP 


STA 


APHM 


LDX 


MVLNG+1 


INX 




LDY 


MVLNG 


BNE 


:EXP6 


BEQ 


:EXP7 



ADD ECSIZE TO 
ALL TABLE ENTRIES 
FROM EXPAND AT ADR 
TO HIMEM 



SET NEW APL 
HI MEM TO 
MEMTOP 

X = MVLNG[H] 
PLUS ONE 
Y = MVLNG[L] 
TEST ZERO LENGTH 
BR IF LOW = 



A8E7 88 
A8E8 C69A 
A8EA C69C 



:EXP4 DEY 

DEC MVFA+1 
DEC MVTA+1 



DEC MVLNG [L] 
DEC MVFA[H] 
DEC MVTA[H] 



A8EC B199 

A8EE 91 9B 

A8F0 88 

A8F1 D0F9 "A8EC 



:EXP5 LDA [MVFA],Y 

STA [MVTA],Y 
:EXP6 DEY 

BNE :EXP5 



MVFA BYTE 

TO MVTA 

DEC COUNT LOW 

BR IF NOT ZERO 



A8F3 B199 
A8F5 919B 



LDA 
STA 



[MVFA],Y 
[MVTA],Y 



MOVE THE ZERO BYTE 



A8F7 :EXP7 

A8F7 CA DEX 

A8F8 D0ED "A8E7 BNE 

A8FA 60 RTS 



:EXP4 



IF MVLNG[H] IS NOT 
ZERO THEN MOVE 256 MORE 

ELSE 
DONE 



CONTRACT 



A8FB A900 



A8FD 




A8FD 


84A4 


A8FF 


85A5 


A901 


38 


A902 


A590 


A904 


F500 


A906 


49FF 


A908 


A8 


A909 


C8 


A90A 


84A2 


A90C 


A591 


A90E 


F501 


A910 


85A3 


A912 


B500 


A914 


E5A2 


A916 


8599 


A918 


B501 



; CONTLOW 


! 


SETS 


CONTLOW LDA #0 


CONTRACT 




STY 


ECSIZE 


STA 


ECSIZE+1 


SEC 




LDA 


MEMTOP 


SBC 


0,X 


EOR 


#?FF 


TAY 




INY 




STY 


MVLNG 


LDA 


MEMTOP+1 


SBC 


1,X 


STA 


MVLNG+1 


LDA 


0,X 


SBC 


MVLNG 


STA 


MVFA 


LDA 


1,X 



X = ZERO PAGE ADR OF TABLE AT WHICH 

CONTRACTION WILL START 

Y = CONTRACT SIZE IN BYTES [LOW] 

A = CONTRACT SIZE IN BYTES [HI] 



SAVE CONTRACT SIZE 



FORM MOVE LENGTH [LOW] 

MVLNG[L] = $100- 
[MEMTOP[L]] - CON AT 
VALUE [L] 

THIS MAKES START Y AT 
MOVE HAVE A 2 ' S COMPLEMENT 
REMAINDER IN IT 

FORM MOVE LENGTH[HIGH] 



FORM MOVE FROM ADR [MVFA] 
MVFA = CON AT VALUE 
MINUS MVLNG[L] 
DURING MOVE MVLNG[L] 



182 



Source Code 



A91A E900 
A91C 859A 



A91E 869B 



SBC 
STA 



#0 
MVFA+1 



WILL BE ADDED BACK INTO 
MVFA IN [IND],Y INST 

TEMP SAVE OF CON AT DISPL 



A920 


38 




:CONTl 


SEC ; SUB 


A921 


B500 




LDA 


0,X 


A923 


E5A4 




SBC 


ECSIZE 


A925 


9500 




STA 


0,X 


A92 7 


B501 




LDA 


1,X 


A929 


E5A5 




SBC 


ECSIZE+1 


A92B 


9501 




STA 


1,X 


A92D 


E8 




INX 




A92E 


E8 




INX 




A92F 


E092 




CPX 


#MEMTOP+2 


A931 


90ED 


~A920 


BCC 


:CONTl 


A933 


850F 




STA 


APHM+1 


A935 


A590 




LDA 


MEMTOP 


A937 


850E 




STA 


APHH 


A939 


A69B 




LDX 


MVTA 


A93B 


B500 




LDA 


0,X 


A93D 


E5A2 




SBC 


MVLNG 


A93F 


859B 




STA 


MVTA 


A941 


B501 




LDA 


1,X 


A943 


E900 




SBC 


#0 


A945 


859C 




STA 


MVTA+1 


A947 






FMOVER 




A947 


A6A3 




LDX 


MVLNG+1 


A949 


E8 




INX 




A94A 


A4A2 




LDY 


MVLNG 


A94C 


D006 


"A954 


BNE 


:CONT2 


A94E 


F00B 


"A95B 


BEQ 


: CONT4 


A950 


E69A 




:CONT3 


INC MVFA+ 


A952 


E69C 




INC 


MVTA+1 


A954 


B199 




:CONT2 


LDA [MVFA 


A956 


91 9B 




STA 


[MVTA],Y 


A958 


C8 




INY 




A959 


D0F9 


"A954 


BNE 


:CONT2 


A95B 






:CONT4 




A95B 


CA 




DEX 




A95C 


D0F2 


"A950 


BNE 


:CONT3 


A95E 


60 




RTS 





SUBTRACT ECSIZE FROM 



ALL TABLE ENTRY FROM 
CON AT ADR TO HIMEM 



SET NEW APL 
HI MEM TO 
MEMTOP 



FORM MOVE TO ADR [MVTA] 
MVTA = NEW CON AT VALUE 
MINUS MVLNG [L] 
DURING MOVE MVLNG[L] 
WILL BE ADDED BACK INTO 
MVTA IN [INO],Y INST 



GET MOVE LENGTH HIGH 
INC SO MOVE CAN BNE 
GET MOVE LENGTH LOW 
IF NOT ZERO GO 
BR IF LOW = 

;INC MVFA[H] 
; INC MVTA[H] 

GET MOVE FROM BYTE 
SET MOVE TO BYTE 
INCREMENT COUNT LOW 
BR IF NOT ZERO 



DECREMENT COUNT HIGH 
BR IF NOT ZERO 
ELSE DONE 



Execute Control 

A95F LOCAL 

EXECNL — Execute Next Line 

START PROGRAM EXECUTOR 



A95F 

A95F 201BB8 



EXECNL 
JSR 



EXECNS — Execute Next Statement 



SET UP LIN & NXT STMT 



A962 




EXECNS 




A962 


20F4A9 


JSR 


TSTBRK 


A965 


D035 "A99C 


BNE 


:EXBRK 


A967 


A4A7 


LDY 


NXTSTD 


A969 


C49F 


CPY 


LLNGTH 


A96B 


B01C "A989 


BCS 


:EXEOL 



TEST BREAK 

BR IF BREAK 
GET PTR TO NEXT STMT L 
AT END OF LINE 

BR IF EOL 



183 



Source Code 



A96D 


B18A 


A96F 


85A7 


A971 


98 


A972 


C8 


A973 


B18A 


A975 


C8 


A976 


84A8 


A978 


207EA9 


A97B 


4C62A9 



A97E 

A97E +0A 
A97F AA 



A980 
A983 
A984 
A987 
A988 



BD00AA 

48 

BD01AA 

48 

60 



LDA 
STA 
TYA 
I NY 
LDA 
I NY 
STY 

JSR 
JMP 



ASL 
TAX 
LDA 
PHA 
LDA 
PHA 
RTS 



[STMCUR], Y 
NXTSTD 

[STMCUR], Y 

STINDEX 

:STGO 
EXECNS 



STETAB.X 

STETAB+l.X 



GET NEW STMT LENGTH 

SAVE AS FUTURE STMT LENGTH 

Y=DISPL TO THIS STMT LENGTH 

PLUS 1 IS DISPL TO CODE 

GET CODE 

INC TO STMT MEAT 

SET WORK INDEX 

GO EXECUTE 

THEN DO NEXT STMT 



GET ADR AND 
PUSH TO STACK 

AND GO TO 
VIA 
RTS 



A989 :EXEOL 

A989 A001 LDY #1 

A98B B18A LDA [STMCUR], Y 

A98D 3010 "A99F BMI :EXFD 



BR IF DIR 



A98F A59F 

A991 20D0A9 

A994 20E2A9 

A997 10C6 "A95F 

A999 4C8DB7 

A99C 4C93B7 

A99F 4C5DA0 



LDA 
JSR 
JSR 
BPL 

EXDONE JMP 
EXBRK JMP 
EXFD JMP 



LLNGTH 
GNXTL 
TENDST 
EXECNL 



XEND 

XSTOP 

SNX3 



;GET LINE LENGTH 
;INC STMCUR 
;TEST END STMT TABLE 
;BR NOT END 

; GO BACK TO SYNTAX 

; BREAK, DO STOP 

! GO TO SYNTAX VIA READY MSG 



GETSTMT — Get Statement in Statement Table 



SEARCH FOR STMT THAT HAS TSLNUM 
SET STMCUR TO POINT TO IT IF FOUND 
OR TO WHERE IT WOULD GO IF NOT FOUND 
CARRY SET IF NOT FOUND 



GETSTMT 



SAVE CURRENT LINE ADDR 



A9A2 
A9A4 
A9A6 
A9A8 
A9AA 
A9AC 



A58A 
85BE 
A58B 
85BF 
A589 
A488 



LDA 
STA 
LDA 
STA 
LDA 
LDY 



STMCUR 

SAVCUR 

STMCUR+1 

SAVCUR+1 

STMTAB+1 

STMTAB 



; START AT TOP OF TABLE 



A9AE 858B 
A9B0 848A 



A9B2 
A9B4 
A9B6 
A9B8 
A9BA 
A9BC 
A9BD 
A9BF 
A9C1 
A9C3 
A9C5 
A9C6 
A9C6 



A001 

B18A 

C5A1 

900D 

D00A 

88 

B18A 

C5A0 

9004 

D001 

18 

60 



"A9C7 
'A9C6 



A9C7 
'A9C6 



A9C7 20DDA9 



STA 
STY 



GS2 

LDA 
CMP 
BCC 
BNE 
DEY 
LDA 
CMP 
BCC 
BNE 
CLC 
:GSRT1 
RTS 

:GS3 



STMCUR+1 
STMCUR 



#1 
[STMCUR], Y 
TSLNUM+1 

GS3 

GSRT1 

GS3 
[STMCUR], Y 
TSLNUM 
:GS3 
:GSRT1 



;SET STMCUR 



GET STMT LNO [HI] 

TEST WITH TSLNUM 

BR IF S<TS 

BR IF S>TS 

S=TS, TEST LOW BYTE 



;BR S<TS 
;BR S>TS 
;S=TS, CLEAR CARY 

;AND RETURN [FOUND] 

;GO GET THIS GUYS LENGTH 



184 



Source Code 



A9CA 


20D0A9 


JSR 


GNXTL 


A9CD 
A9D0 


4CB2A9 


JMP 
GNXTL 


:GS2 


A9D0 


18 


CLC 




A9D1 


658A 


ADC 


STMCUR 


A9D3 


858A 


STA 


STMCUR 


A9D5 


A8 


TAY 




A9D6 


A58B 


LDA 


STMCUR+1 


A9D8 


6900 


ADC 


#0 


A9DA 


858B 


STA 


STMCUR+1 


A9DC 


60 


RTS 




A9DD 


A002 


GETLL LDY #2 


A9DF 


B18A 


LDA 


[STMCUR], Y 


A9E1 


60 


RTS 





;ADD LENGTH TO STMCUR 



TENDST — Test End of Statement Table 



A9E2 




TENDST 






A9E2 


A001 


LDY 




#1 


A9E4 


B18A 


LDA 




[STMCUR], Y 


A9E6 


60 


RTS 






A9E7 




XREM 






A9E7 




XDATA 






A9E7 


60 


TESTRTS 


RTS 





INDEX TO CNO [ 'I] 
GET CNO [HI] 



XBYE — Execute BYE 



8 




XBYE 




8 


2041BD 


JSR 


CLSALL 


B 


4C71E4 


JMP 


BYELOC 



CLOSE 1-7 
EXIT 



XDOS — Execute DOS 



A9EE 


2041BD 


A9P1 


6C0A00 


TSTBR 

A9F4 


K — Tes 


A9F4 


A000 


A9F6 


A511 


A9F8 


D004 " 


A9FA 


A0FF 


A9FC 


8411 


A9FE 


98 


A9FF 


60 



JSR 




CLSALL 


JMP 




[DOSLOC] 


eak 

TSTBRK 






LDY 




#0 


LDA 




BRKBYT 


BNE 




:TB2 


LDY 




#?FF 


STY 




BRKBYT 


:TB2 


TYA 




RTS 







CLOSE 1-7 
GO TO DOS 



; LOAD BREAK BYTE 



SET COND CODE 
DONE 



Statement Execution Table 

STETAB-STATEMENT EXECUTION TABLE 

-CONTAINS STMT EXECUTION ADR 
-MUST BE IN SAME ORDER AS SNTAB 



AA00 




STETAB 








AA00 




FDB 




XREM-1 




AA00 


+A9E6 


DW 




REV (XREM-1 ) 




AA02 




FDB 




XDATA-1 




AA02 


+A9E6 


DW 




REV (XDATA-1 ) 






= 0001 


CDATA 


EQU 


(*-STETAB)/2- 


-1 


AA04 




FDB 




XINPUT-1 




AA04 
AA06 


+B315 


DW 
FDB 




REV (XINPUT-1) 
XCOLOR-1 




AA06 


+BA28 


DW 




REV (XCOLOR-1 ) 




AA08 




FDB 




XLIST-1 




AA08 


+B482 


DW 




REV (XLIST-1) 






= 0004 


CLIST 


EQU 


(*-STETAB) /2 


-1 



185 



Source Code 



AA0A 




FDB 


XENTER-1 


AA0A 


+BACA 


DW 


REV (XENTER-1) 


AA0C 




FDB 


XLET-1 


AA0C 


+AADF 


DW 


REV (XLET-1 ) 


AA0E 




FDB 


XIF-1 


AA0E 


+B777 


DW 


REV (XIF-1) 


AA10 




FDB 


XFOR-1 


AA10 


+B64A 


DW 


REV (XFOR-1) 




= 0008 


CFOR 


EQU (*-STETAB)/2-l 


AA12 




FDB 


XNEXT-1 


AA12 


+B6CE 


DW 


REV (XNEXT-1 ) 


AA14 




FDB 


XGOTO-1 


AA14 


+B6A2 


DW 


REV (XGOTO-1 ) 


AA16 




FDB 


XGOTO-1 


AA16 


+B6A2 


DW 


REV (XGOTO-1) 


AA18 




FDB 


XGOSUB-1 


AA18 


+B69F 


DW 


REV (XGOSUB-1) 




= 000C 


CGOSUB 


EQU (*-STETAB)/2-l 


AA1A 




FDB 


XTRAP-1 


AA1A 


+B7E0 


DW 


REV (XTRAP-1) 


AA1C 




FDB 


XBYE-1 


AA1C 


+A9E7 


DW 


REV (XBYE-1) 


AA1E 




FDB 


XCONT-1 


AA1E 


+B7BD 


DW 


REV (XCONT-1 ) 


AA20 




FDB 


XCOM-1 


AA20 


+B1D8 


DW 


REV (XCOM-1) 


AA22 




FDB 


XCLOSE-1 


AA22 


+BC1A 


DW 


REV (XCLOSE-1) 


AA24 




FDB 


XCLR-1 


AA24 


+B765 


DW 


REV (XCLR-1 ) 


AA26 




FDB 


XDEG-1 


AA26 


+B260 


DW 


REV (XDEG-1) 


AA28 




FDB 


XDIM-1 


AA28 


+B1D8 


DW 


REV (XDIM-1) 


AA2A 




FDB 


XEND-1 


AA2A 


+B78C 


DW 


REV (XEND-1) 


AA2C 




FDB 


XNEW-1 


AA2C 


+A00B 


DW 


REV (XNEW-1) 


AA2E 




FDB 


XOPEN-1 


AA2E 


+BBEA 


DW 


REV (XOPEN-1) 


AA30 




FDB 


XLOAD-1 


AA30 


+BAFA 


DW 


REV (XLOAD-1 ) 


AA32 




FDB 


XSAVE-1 


AA32 


+BB5C 


DW 


REV (XSAVE-1 ) 


AA34 




FDB 


XSTATUS-1 


AA34 


+BC27 


DW 


REV (XSTATUS-1) 


AA36 




FDB 


XNOTE-1 


AA36 


+BC35 


DW 


REV (XNOTE-1 ) 


AA38 




FDB 


XPOINT-1 


AA38 


+BC4C 


DW 


REV (XPOINT-1) 


AA3A 




FDB 


XXIO-1 


AA3A 


+BBE4 


DW 


REV (XXIO-1) 


AA3C 




FDB 


XON-1 


AA3C 


+B7EC 


DW 


REV (XON-1) 




= 001E 


CON 


EQU (*-STETAB)/2-l 


AA3E 




FDB 


XPOKE-1 


AA3E 


+B24B 


DW 


REV (XPOKE-1) 


AA40 




FDB 


XPRINT-1 


AA40 


+B3B5 


DW 


REV (XPRINT-1) 


AA42 




FDB 


XRAD-1 


AA42 


+B265 


DW 


REV (XRAD-1) 


AA44 




FDB 


XREAD-1 


AA44 


+B282 


DW 


REV (XREAD-1) 




= 0022 


CREAD 


EQU (*-STETAB)/2-l 


AA46 




FDB 


XREST-1 


AA46 


+B26A 


DW 


REV (XREST-1) 


AA48 




FDB 


XRTN-1 


AA4B 


+B718 


DW 


REV (XRTN-1) 


AA4A 




FDB 


XRUN-1 


AA4A 


+B74C 


DW 


REV (XRUN-1) 


AA4C 




FDB 


XSTOP-1 



186 



Source Code 



AA4C 


+B792 


DW 


REV (XSTOP-1) 


AA4E 




PDB 


XPOP-1 


AA4E 


+B840 


DW 


REV (XPOP-1) 


AA50 




FDB 


XPRINT-1 


AA50 


+B3B5 


DW 


REV (XPRINT-1) 


AA52 




FDB 


XGET-1 


AA52 


+BC7E 


DW 


REV (XGET-1 ) 


AA54 




FDB 


XPUT-1 


AA54 


+BC71 


DW 


REV (XPUT-1) 


AA56 




FDB 


XGR-1 


AA56 


+BA4P 


DW 


REV (XGR-1) 


AA58 




FDB 


XPLOT-1 


AA58 


+BA75 


DW 


REV (XPLOT-1 ) 


AA5A 




FDB 


XPOS-1 


AA5A 


+BA15 


DW 


REV (XPOS-1 ) 


AA5C 




FDB 


XDOS-1 


AA5C 


+A9ED 


DW 


REV (XDOS-1 ) 


AA5E 




FDB 


XDRAWTO-1 


AA5E 


+BA30 


DW 


REV (XDRAWTO-1) 


AA60 




FDB 


XSETC0L0R-1 


AA60 


+B9B6 


DW 


REV (XSETC0L0R-1 ) 


AA62 




FDB 


XLOCATE-1 


AA62 


+BC94 


DW 


REV (XLOCATE-1 ) 


AA64 




FDB 


XSOUND-1 


AA64 


+B9DC 


DW 


REV (XSOUND-1 ) 


AA66 




FDB 


XLPRINT-1 


AA66 


+B463 


DW 


REV (XLPRINT-1) 


AA68 




FDB 


XCSAVE-1 


AA68 


+BBA3 


DW 


REV (XCSAVE-1) 


AA6A 




FDB 


XCLOAD-1 


AA6A 


+BBAB 


DW 


REV (XCLOAD-1) 


AA6C 




FDB 


XLET-1 


AA6C 


+AADF 


DW 


REV (XLET-1 ) 




= 0036 


CILET 


EQU (*-STETAB)/2-l 


AA6E 




FDB 


XERR-1 


AA6E 


+B91D 


DW 


REV (XERR-1) 




= 0037 


CERR 


EQU (*-STETAB)/2-l 



Operator Execution Table 



OPETAB - OPERATOR EXECUTION TABLE 

- CONTAINS OPERATOR EXECUTION ADR 

- MUST BE IN SAME ORDER AS OPNTAB 



AA70 




OPETAB 




AA70 




FDB 


XPLE-1 


AA70 


+ACB4 


DW 


REV (XPLE-1) 


AA72 




FDB 


XPNE-1 


AA72 


+ACBD 


DW 


REV (XPNE-1) 


AA74 




FDB 


XPGE-1 


AA74 


+ACD4 


DW 


REV (XPGE-1 ) 


AA76 




FDB 


XPLT-1 


AA76 


+ACC4 


DW 


REV (XPLT-1 ) 


AA78 




FDB 


XPGT-1 


AA78 


+ACCB 


DW 


REV (XPGT-1 ) 


AA7A 




FDB 


XPEQ-1 


AA7A 


+ACDB 


DW 


REV (XPEQ-1 ) 


AA7C 




FDB 


XPPOWER-1 


AA7C 


+B164 


DW 


REV (XPPOWER-1) 


AA7E 




FDB 


XPMUL-1 


AA7E 


+AC95 


DW 


REV (XPMUL-1 ) 


AA80 




FDB 


XPPLUS-1 


AA80 


+AC83 


DW 


REV (XPPLUS-1 ) 


AA82 




FDB 


XPMINUS-1 


AA82 


+AC8C 


DW 


REV (XPMINUS-1) 


AA84 




FDB 


XPDIV-1 


AA84 


+AC9E 


DW 


REV (XPDIV-1) 


AA86 




FDB 


XPNOT-1 


AA86 


+ACF8 


DW 


REV (XPNOT-1 ) 


AA88 




FDB 


XPOR-1 


AA88 


+ACED 


DW 


REV (XPOR-1 ) 



187 



Source Code 



AA8A 




AA8A 


+ACE2 


AA8C 




AA8C 


+AB1E 


AA8E 




AA8E 


+AD7A 


AA90 




AA90 


+AD5E 


AA92 




AA92 


+AEA2 


AA94 




AA94 


+ACB4 


AA96 




AA96 


+ACBD 


AA98 




AA98 


+ACD4 


AA9A 




AA9A 


+ACC4 


AA9C 




AA9C 


+ACCB 


AA9E 




AA9E 


+ACDB 


AAA0 




AAA0 


+ACB3 


AAA2 




AAA2 


+ACA7 


AAA4 




AAA4 


+AE25 


AAA6 




AAA6 


+AD85 


AAA8 




AAA8 


+AD81 


AAAA 




AAAA 


+AD7A 


AAAC 




AAAC 


+AD81 


AAAE 




AAAE 


+AD78 


AAB0 




AAB0 


+B048 


AAB2 




AAB2 


+B066 


AAB4 




AAB4 


+B0B9 


AAB6 




AAB6 


+B011 


AAB8 




AAB8 


+AFFF 


AABA 




AABA 


+AFC9 


AABC 




AABC 


+B01B 


AABE 




AABE 


+B12E 


AAC0 




AAC0 


+B124 


AAC2 




AAC2 


+AFE0 


AAC4 




AAC4 


+B11A 


AAC6 




AAC6 


+B08A 


AAC8 




AAC8 


+AFEA 


AACA 




AACA 


+B14C 


AACC 




AACC 


+B138 


AACE 




AACE 


+B142 



FDB 


XPAND-1 


DW 


REV (XPAND-1 ) 


FDB 


XPLPRN-1 


DW 


REV (XPLPRN-1) 


FDB 


XPRPRN-1 


DW 


REV (XPRPRN-1) 


FDB 


XPAASN-1 


DW 


REV (XPAASN-1) 


FDB 


XSAASN-1 


DW 


REV (XSAASN-1 ) 


FDB 


XPSLE-1 


DW 


REV (XPSLE-1 ) 


FDB 


XPSNE-1 


DW 


REV (XPSNE-1) 


FDB 


XPSGE-1 


DW 


REV (XPSGE-1) 


FDB 


XPSLT-1 


DW 


REV (XPSLT-1) 


FDB 


XPSGT-1 


DW 


REV (XPSGT-1 ) 


FDB 


XPEQ-1 


DW 


REV (XPEQ-1) 


FDB 


XPUPLUS-1 


DW 


REV (XPUPLUS-1) 


FDB 


XPUMINUS-1 


DW 


REV (XPUMINUS-1) 


FDB 


XPSLPRN-1 


DW 


REV (XPSLPRN-1 ) 


FDB 


XPALPRN-1 


DW 


REV (XPALPRN-1) 


FDB 


XPDLPRN-1 


DW 


REV (XPDLPRN-1) 


FDB 


XPFLPRN-1 


DW 


REV (XPFLPRN-1) 


FDB 


XDPSLP-1 


DW 


REV (XDPSLP-1 ) 


FDB 


XPACOM-1 


DW 


REV (XPACOM-1) 


FDB 


XPSTR-1 


DW 


REV (XPSTR-1) 


FDB 


XPCHR-1 


DW 


REV (XPCHR-1) 


FDB 


XPUSR-1 


DW 


REV (XPUSR-1) 


FDB 


XPASC-1 


DW 


REV (XPASC-1) 


FDB 


XPVAL-1 


DW 


REV (XPVAL-1) 


FDB 


XPLEN-1 


DW 


REV (XPLEN-1) 


FDB 


XPADR-1 


DW 


REV (XPADR-1) 


FDB 


XPATN-1 


DW 


REV (XPATN-1) 


FDB 


XPCOS-1 


DW 


REV (XPCOS-1) 


FDB 


XPPEEK-1 


DW 


REV (XPPEEK-1) 


FDB 


XPSIN-1 


DW 


REV (XPSIN-1) 


FDB 


XPRND-1 


DW 


REV (XPRND-1) 


FDB 


XPFRE-1 


DW 


REV (XPFRE-1) 


FDB 


XPEXP-1 


DW 


REV (XPEXP-1) 


FDB 


XPLOG-1 


DW 


REV (XPLOG-1) 


FDB 


XPL10-1 


DW 


REV (XPL10-1) 



188 



Source Code 



AAD0 
AAD0 
AAD2 
AAD2 
AAD4 
AAD4 
AAD6 
AAD6 
AAD8 
AAD8 
AADA 
AADA 
AADC 
AADC 
AADE 
AADE 



+B156 
+AD18 
+B0AD 
+B0DC 
+B021 
+B025 
+B029 
+B02D 



FDB 


XPSQR-1 


DW 


REV (XPSQR-1) 


FDB 


XPSGN-1 


DW 


REV (XPSGN-1 ) 


FDB 


XPABS-1 


DW 


REV (XPABS-1) 


FDB 


XPINT-1 


DW 


REV (XPINT-1 ) 


FDB 


XPPDL-1 


DW 


REV (XPPDL-1) 


FDB 


XPSTICK-1 


DW 


REV (XPSTICK-1) 


FDB 


XPPTRIG-1 


DW 


REV (XPPTRIG-1 ) 


FDB 


XPSTRIG-1 


DW 


REV (XPSTRIG-1) 



Execute Expression 



EXEXPR — Execute Expression 



AAE0 




XLET 




AAE0 




EXEXPR 




AAE0 


202EAB 


JSR 


EXP I NT 


AAE3 




: EXNXT 




AAE3 


203EAB 


JSR 


:EGTOKEN 


AAE6 


B006 "AAEE 


BCS 


:EXOT 


AAE8 


20BAAB 


JSR 


ARGPUSH 


AAEB 


4CE3AA 


JMP 


: EXNXT 


AAEE 


85AB 


:EXOT STA 


EXSVOP 


AAF0 


AA 


TAX 




AAF1 


BD2FAC 


LDA 


0PRTAB-16,X 


AAF4 




LSRA 




AAF4 


+4A 


LSR 


A 


AAF5 




LSRA 




AAF5 


+4A 


LSR 


A 


AAF6 




LSRA 




AAF6 


+4A 


LSR 


A 


AAF7 




LSRA 




AAF7 


+4A 


LSR 


A 


AAF8 


8 5 AC 


STA 


EXSVPR 


AAFA 


A4A9 


:EXPTST LDY 


OPSTKX 


AAFC 


B180 


LDA 


[ARGSTK], Y 


AAFE 


AA 


TAX 




AAFF 


BD2FAC 


LDA 


OPRTAB-16.X 


AB02 


290F 


AND 


#$0F 


AB04 


C5AC 


CMP 


EXSVPR 


AB06 


900D ~AB15 


BCC 


:EOPUSH 


AB08 


AA 


TAX 




AB09 


F014 "AB1F 


BEQ 


:EXEND 


AB0B 




EXOPOP 




AB0B 


B180 


LDA 


[ARGSTK], Y 


AB0D 


E6A9 


INC 


OPSTKX 


AB0F 


2020AB 


JSR 


:EXOP 


AB12 


4CFAAA 


JMP 


:EXPTST 


AB15 


A5AB 


:EOPUSH LDA 


EXSVOP 


AB17 


88 


DEY 




AB18 


9180 


STA 


[ ARGSTK ],Y 


AB1A 


B4A9 


STY 


OPSTKX 


ABIC 


4CE3AA 


JMP 


: EXNXT 


AB1F 




XPLPRN 





GO GET TOKEN 
BR IF OPERATOR 



PUSH ARG 

GO FOR NEXT TOKEN 



SAVE OPERATOR 



GET OP PREC 

SHIFT FOR GOES ON TO PREC 



SAVE GOES ON PREC 

GET OP STACK INDEX 
GET TOP OP 

GET TOP OP PREC 

[TOP OP]: [NEW OP] 
IF T<N, PUSH NEW 

ELSE POP 
IF POP SOE 
THEN DONE 



RE-GET TOS OP 

DEC OP STACK INDEX 

GET EXECUTE OP 

GO TEST OP WITH NEW TOS 

GET OP TO PUSH 

DEC TO NEXT ENTRY 

SET OP IN STACK 

SAVE NEW OP STACK INDEX 

GO GET NEXT TOKEN 



189 



Source Code 



AB1F 


60 


: EXEND RTS 




DONE EXECUTE EXPR 


AB20 




:EXOP 






AB20 


38 


SEC 




SUBSTRACT FOR REL 


AB21 


E91D 


SBC 


#CSROP 


VALUE OF FIRST REAL OP 


AB23 




AS LA 




VALUE * 2 


AB23 


+0A 


ASL 


A 




AB24 


AA 


TAX 






AB25 


BD70AA 


LDA 


OPETAB.X 


PUT OP EXECUTION 


AB28 


48 


PHA 




ROUTINE ON STACK 


AB29 


BD71AA 


LDA 


0PETAB+1,X 


AND GOTO 


AB2C 


48 


PHA 




VIA 


AB2D 


60 


RTS 




RTS 



Initialize Expression Parameters 



AB2E 
AB2E 
AB30 
AB32 
AB34 
AB36 
AB37 
AB39 
AB3B 
AB3D 



A0FF 

A911 

9180 

84A9 

C8 

84B0 

84AA 

84B1 

60 



EXP I NT 
LDY 
LDA 
STA 
STY 
I NY 
STY 
STY 
STY 
RTS 



#$FF 
#CSOE 

[ARGSTK],Y 
OPSTKX 

COMCNT 
ARSTKX 
ADFLAG 



GETTOK — Get Next Token and Classify 



AB3E 
AB3E 
AB3E 
AB40 
AB42 
AB44 



A4A8 
E6A8 
B18A 
3043 "AB89 



GETTOK 

rEGTOKEN 
LDY 
INC 
LDA 
BMI 



STINDEX 
ST INDEX 
[STMCUR],Y 
: EGTVAR 



OPERATOR 
STACK 

AND INITIALIZE 

ARG STACK 
ASSIGN FLAG 



GET STMT INDEX 
INC TO NEXT 
GET TOKEN 
BR IF VAR 



AB46 C90F 

AB48 9003 "AB4D 

AB4A F013 "AB5F 

AB4C 60 



CMP #?0F 

BCC : EGNC 

BEQ :EGSC 
RTS 



TOKEN: $0F 

BR IF $0E, NUMERIC CONST 
BR IF $0F, STR CONST 
RTN IF OPERATOR 



AB4D 




AB4D 


A200 


AB4F 


C8 


AB50 


B18A 


AB52 


95D4 


AB54 


E8 


AB55 


E006 


AB57 


90F6 


AB59 


C8 


AB5A 


A900 


AB5C 


AA 


AB5D 


F022 


AB5F 


C8 


AB60 


B18A 


AB62 


A28A 


AB64 




AB64 


85D6 


AB66 


85D8 


AB68 


C8 


AB69 


98 


AB6A 


18 


AB6B 


7500 


AB6D 


85D4 


AB6F 


A900 


AB71 


85D7 


AB73 


85D9 


AB75 


7501 


AB77 


85D5 



"AB4F 



NCTOFR0 

: EGNC LDX 

:EGT1 INY 

LDA 

STA 

I NX 

CPX 

BCC 

INY 

LDA 

TAX 

BEQ 

:EGSC 

LDA 

LDX 
RISC 

STA 

STA 

INY 

TYA 

CLC 

ADC 

STA 

LDA 

STA 

STA 

ADC 

STA 



[STMCUR], Y 
FR0.X 

#6 
:EGT1 

tEVSCALER 



[STMCUR], Y 
ISTMCUR 

VTYPE+EVSLEN 
VTYPE+EVSDIM 



0,X 

VTYPE+EVSADR 

#0 

VTYPE+EVSLEN+1 

VTYPE+EVSDIM+1 

1,X 

VTYPE+EVSADR+1 



INC LINE INDEX 

GET VALUE FROM STMT TBL 

AND PUT INTO FR0 



INY Y BEYOND CONST 
ACU=SCALER 
X = VAL NO 
GO SET REM 

INC Y TO LENGTH BYTE 
GET LENGTH 
POINT TO SMCUR 

SET AS LENGTH 
AND DIM 

ACU=DISPL TO STR 

DISPL PLUS ADR 
IS STR ADR 
SET = 
LENGTH HIGH 
DIM HIGH 
FINISH ADR 



190 



Source Code 



AB79 


98 


AB7A 


65D6 


AB7C 


A8 


AB7D 


A200 


AB7F 


A983 


AB81 


85D2 


AB83 


86D3 


AB85 


84A8 


AB87 


18 


AB88 


60 


AB89 




AB89 




AB89 


2028AC 


AB8C 


B19D 


AB8E 


99D200 


AB91 


C8 


AB92 


C008 


AB94 


90F6 "i 


AB96 


18 


AB97 


60 



TYA 








ACU=DISPL TO STR 


ADC 




VTYPE+EVSLEN 




PLUS STR LENGTH 


TAY 








IS NEW INDEX 


LDX 




#00 




VAR NO = 


LDA 




#EVSTR+EVSDTA+EVDIM ; TYPE = STR 


:EGST 


STA 


VTYPE 




SET TYPE 


STX 




VNUM 




SET NUM 


STY 




STINDEX 




SET NEW INDEX 


CLC 








INDICATE VALUE 


:EGRTS 


RTS 






RETURN 


GETVAR 
: EGTVAR 










JSR 




GWTADR 




GET WT ADR 


:EGT2 


LDA 


[WWTPT] 


Y 


; MOVE WT ENT 


STA 




VTYPE, Y 




TO FR0 


I NY 










CPY 




#8 






BCC 




:EGT2 






CLC 








INDICATE VALUE 


RTS 








RETURN 



AAPSTR — Pop String Argument and Make Address Absolute 



AB98 20F2AB 



AAPSTR JSR 



| GO POP ARG 



GSTRAD — Get String [ABS] Address 



AB9B 






GSTRAD 








AB9B 


A902 




LDA 




#EVSDTA 


LOAD TRANSFORMED BIT 


AB9D 


24D2 




BIT 




VTYPE 


TEST STRING ADR TRANSFORM 


AB9F 


D015 


"ABB6 


BNE 




: GSARTS 


BR IF ALREADY TRANSFORMED 


ABA1 


05D2 




ORA 




VTYPE 


TURN ON TRANS BIT 


ABA 3 


85D2 




STA 




VTYPE 


AND SET 


ABA 5 






RORA 




SHIFT DIM BIT TO CARRY 


ABA 5 


+6A 




ROR 




A 




ABA 6 


900F 


~ABB7 


BCC 




:GSND 




ABA 8 


18 




CLC 








ABA 9 


A5D4 




LDA 




VTYPE+EVSADR 


STRING ADR " STRING DISPL 
+ STARP 


ABAB 


658C 




ADC 




STARP 




ABAD 


85D4 




STA 




VTYPE+EVSADR 




ABAF 


A8 




TAY 








ABB0 


A5D5 




LDA 




VTYPE+EVSADR+1 




ABB2 


658D 




ADC 




STARP+1 




ABB4 


85D5 




STA 




VTYPE+EVSADR+1 




ABB6 


60 




: GSARTS 


RTS 






ABB7 


202EB9 


:GSND 


JSR 


ERRDIM 





ARGPUSH — Push FRO to Argument Stack 



ABBA 


E6AA 


ABBC 


A5AA 


ABBE 




ABBE 


+0A 


ABBF 




ABBF 


+0A 


ABC0 




ABC0 


+0A 


ABC1 


C5A9 


ABC 3 


B00D 


ABC 5 


A8 


ABC 6 


88 


ABC 7 


A207 


ABC 9 


B5D2 


ABCB 


9180 



ARGPUSH 




INC 


ARSLVL 


LDA 


ARSLVL 


ASLA 




ASL 


A 


ASLA 




ASL 


A 


ASLA 




ASL 


A 


CMP 


OPSTKX 


BCS 


:APERR 


TAY 




DEY 




LDX 


*7 



INC ARG STK LEVEL 
ACU = ARG STACK LEVEL 
TIMES 8 



TEST EXCEED MAX 

BR IF GT MAX 

Y = NEXT ENTRY ADR 

MINUS ONE 

X = 7 FOR 8 



:APH1 LDA VTYPE, X 
STA [ARGOPSD.Y 



MOVE FR0 
TO ARGOPS 



191 



Source Code 



ABCD 


88 


DEY 


r BACKWARDS 


ABCE 


CA 


DEX 




ABCP 


10F8 "ABC9 


BPL :APH1 




ABD1 


60 


RTS 


; DONE 


ABD2 


4C2CB9 


:APERR JMP ERRAOS 


; STACK OVERFLOW 


GETPINT — Get Positive Integer from Expression 




ABD5 




GETPINT 




ABD5 


20E0AB 


JSR GETINT 


; GO GET INT 


ABD8 




GETPI0 




ABD8 


A5D5 


LDA FR0+1 


; GET HIGH BYTE 


ABDA 


3001 "ABDD 


BMI :GPIERR 


I BR > 3 2 767 


ABDC 


60 


RTS 


; DONE 


ABDD 


4C32B9 


:GPIERR JMP ERRLN 




GEm 


T — Get Integer from Expression 




ABE0 


20E0AA 


GETINT JSR EXEXPR 


; EVAL EXPR 


ABE 3 




GTINTO 




ABE3 


20P2AB 


JSR ARGPOP 


; POP VALUE TO FR0 


ABE6 


4C56AD 


JMP CVFPI 


1 GO CONVERT FR0 TO INT E. 
RETURN 



GET1INT — Get One-Byte Integer from Expression 



ABE9 

ABE9 20D5AB 

ABEC D001 "ABEF 

ABEE 60 

ABEF 

ABEF 203AB9 



GET1INT 
JSR 
BNE 
RTS 

:ERV1 

JSR 



GETPINT 
:ERV1 



ERVAL 

ARGPOP — Pop Argument Stack Entry to FRO or FR1 



ABF2 

ABF2 A5AA 
ABF4 C6AA 
ABF6 

ABF6 +0A 
ABF7 

ABF7 +0A 
ABF8 

ABF8 +0A 
ABF9 A8 
ABFA 88 
ABFB A207 

ABFD BI80 

ABFF 95D2 

AC01 88 

AC02 CA 

AC03 10F8 

AC05 60 



ARGP2 — Pop TOS to FR1 JOS-1 to FRO 



AC06 20F2AB 
AC09 20B6DD 



ARGP2 JSR ARGPOP 
JSR MV0TO1 



AC0C 


4CF2AB JMP 


ARGPOP 


POP1 


— Get a Value in FRO 


- EVA 
POP 


AC0F 


POPl 




AC0F 


20E0AA JSR 


EXEXPR 


AC12 


20F2AB JSR 


ARGPOP 


AC15 


60 RTS 





GET INT <32768 

IF NOT 1 BYTE, THEN ERROR 



ARGPOP 




LDA 


ARSLVL ; 


DEC 


ARSLVL 


ASIA 




ASL 


A 


AS LA 




ASL 


A 


AS LA 




ASL 


A 


TAY 




DEY 




LDX 


#7 '; 


•APOP0 LDA 


[ARGOPS],Y 


STA 


VTYPE.X 


DEY 


; 


DEX 




BPL 


:APOP0 


RTS 


; 



GET ARG STACK LEVEL 
DEC AS LEVEL 
AS LEVEL * 8 



Y = START OF NEXT ENTRY 
MINUS ONE 
X = 7 FOR 8 

; MOVE ARG ENTRY 

BACKWARDS 



DONE 



POP TOS TO FR0 

MOVE FR0 TO FR1 

POP TOS TO FR0 AND RETURN 



EVALUATE EXPRESSION IN STMT LINE & 
POP IT INTO FR0 



EVALUATE EXPRESSION 
PUSH INTO FR0 



192 



Source Code 



RTNVAR — Return V 


ariable to s 


/ariable Value Table fror 


nFRO 


AC16 






RTNVAR 






AC16 


A5D3 




LDA 


VNUM 


GET VAR NUMBER 


AC18 


2028AC 


JSR 


GVVTADR 




AC1B 


A200 




LDX 


#0 




ACID 


B5D2 




:RV1 


LDA VTYPE,X 


MOVE FR0 TO 


AC1P 


919D 




STA 


[WWTPT], Y 


VAR VALUE TABLE 


AC21 


C8 




I NY 






AC22 


E8 




I NX 






AC23 


E008 




CPX 


#8 




AC25 


90F6 


"ACID 


BCC 


:RV1 




AC27 


60 




RTS 




DONE 


GVVTADR — 


Get Val 


ue's Value 


Table Entry Address 




AC28 






GVVTADR 






AC28 


A000 




LDY 


#0 


CLEAR ADR HI 


AC 2 A 


849E 




STY 


WWTPT+l 




AC2C 






AS LA 




MULT VAR NO 


AC2C 


+0A 




ASL 


A 




AC2D 






ASLA 




BY 8 


AC2D 


+0A 




ASL 


A 




AC2E 


269E 




ROL 


WWTPT+l 




AC30 






ASLA 






AC30 


+0A 




ASL 


A 




AC31 


269E 




ROL 


WWTPT+l 




AC33 


18 




CLC 




THEN 


AC34 


6586 




ADC 


WTP 


ADD WTP VALUE 


AC36 


859D 




STA 


WWTPT 


TO FORM ENTRY 


AC38 


A587 




LDA 


WTP+1 


ADR 


AC 3 A 


659E 




ADC 


WWTPT + l 




AC3C 


859E 




STA 


WWTPT+l 




AC3E 


60 




RTS 







Operator Precedence Table 



AC3F 




OPRTAB 




AC3F 


00 


DB 


$00 


AC40 


00 


DB 


$00 


AC41 


00 


DB 


$00 


AC42 


00 


DB 


$00 


AC43 


00 


DB 


$00 


AC 44 


00 


DB 


$00 


AC45 


00 


DB 


$00 


AC46 


00 


DB 


$00 


AC47 


00 


DB 


$00 


AC48 


00 


DB 


$00 


AC49 


00 


DB 


$00 


AC 4 A 


00 


DB 


$00 


AC4B 


00 


DB 


$00 


AC4C 


88 


DB 


$88 


AC4D 


88 


III! 


$88 


AC4E 


88 


DB 


$88 


AC4F 


88 


DB 


$88 


AC 50 


88 


DB 


$88 


AC51 


88 


DB 


$88 


AC52 


CC 


DB 


$CC 


AC53 


AA 


DB 


$AA 


AC54 


99 


DB 


$99 


AC55 


99 


DB 


$99 


AC 56 


AA 


DB 


$AA 


AC57 


77 


DB 


$77 


AC58 


55 


DB 


$55 


AC59 


66 


DB 


$66 


AC 5 A 


F2 


DB 


$F2 



- ENTRIES MUST BE IN SAME ORDER AS OPNTAB 

- LEFT NIBBLE IS TO GO ON STACK PREC 

- RIGHT NIBBLE IS COME OFF STACK PREC 



CDQ 

CSOE 

CCOM 

CDOL 

CEOS 

CSC 

CCR 

CGTO 

CGS 

CTO 

CSTEP 

CTHEN 

CPND 

CLE 

CNE 

CGE 

CGT 

CLT 

CEQ 

CEXP 

CMUL 

CPLUS 

CMINUS 

CDIV 

CNOT 

COR 

CAND 

CLPRN 



193 



Source Code 



AC5B 


4E 


AC5C 


Fl 


AC5D 


Fl 


AC5E 


EE 


AC5F 


EE 


AC60 


EE 


AC61 


EE 


AC62 


EE 


AC63 


EE 


AC64 


DD 


AC65 


DD 


AC66 


P2 


AC67 


P2 


AC68 


P2 


AC69 


F2 


AC 6 A 


F2 


AC6B 


43 


AC6C 


F2 


AC6D 


P2 


AC6E 


F2 


AC6F 


P2 


AC70 


P2 


AC71 


F2 


AC72 


F2 


AC73 


F2 


AC74 


F2 


AC75 


F2 


AC76 


F2 


AC77 


F2 


AC78 


F2 


AC79 


F2 


AC 7 A 


F2 


AC7B 


F2 


AC7C 


F2 


AC7D 


F2 


AC7E 


F2 


AC7F 


F2 


AC80 


F2 


AC81 


F2 


AC82 


F2 


AC83 


F2 



DB 


?4E 


DB 


$F1 


DB 


$F1 


DB 


SEE 


DB 


$EE 


DB 


$EE 


DB 


$EE 


DB 


SEE 


DB 


SEE 


DB 


SDD 


DB 


SDD 


DB 


SF2 


DB 


SF2 


DB 


$F2 


DB 


$F2 


DB 


$F2 


DB 


$43 


DB 


$F2 


DB 


SF2 


DB 


$F2 


DB 


SF2 


DB 


$F2 


DB 


SF2 


DB 


$F2 


DB 


$F2 


DB 


SF2 


DB 


SF2 


DB 


$F2 


DB 


$F2 


DB 


SF2 


DB 


$F2 


DB 


$F2 


DB 


$F2 


DB 


$F2 


DB 


$F2 


DB 


$F2 


DB 


SF2 


DB 


$F2 


DB 


$F2 


DB 


SF2 


DB 


SF2 



CRPRN 

CAASN 

CSASN 

CSLE 

CSNE 

CSGE 

CSLT 

CSGT 

CSEQ 

CUPLUS 

CUMINUS 

CSLPRN 

CALPRN 

CDLPRN 

CFLPRN 

CDSLPR 

CACOM 

; FUNCTIONS 



Miscellaneous Operators 



Miscellaneous Operators' Executors 



AC 84 




XPPLUS 




AC 84 


2006AC 


JSR 


ARGP2 


AC87 


203BAD 


JSR 


FRADD 


AC 8 A 


4CBAAB 


JMP 


ARGPUSH 


AC8D 




XPMINUS 




AC8D 


2006AC 


JSR 


ARGP2 


AC 90 


2041AD 


JSR 


FRSUB 


AC93 


4CBAAB 


JMP 


ARGPUSH 


AC96 




XPMUL 




AC96 


2006AC 


JSR 


ARGP2 


AC99 


2047AD 


JSR 


FRMUL 


AC9C 


4CBAAB 


JMP 


ARGPUSH 


AC9F 




XPDIV 




AC9F 


2006AC 


JSR 


ARGP2 


AC A 2 


204DAD 


JSR 


FRDIV 


AC A 5 


4CBAAB 


JMP 


ARGPUSH 


ACA8 




XPUMINUS 




AC A 8 


20F2AB 


JSR 


ARGPOP 


ACAB 


A5D4 


LDA 


FR0 


ACAD 


4980 


EOR 


#$80 


ACAF 


85D4 


STA 


FR0 


ACB1 
ACB4 


4CBAAB 


JMP 
XPUPLUS 


ARGPUSH 



;GET ARGUMENT INTO FR0 

;GET BYTE WITH SIGN 

,-FLIP SIGN BIT 

; RETURN BYTE WITH SIGN CHANGED 

;PUSH ON STACKS 



194 



Source Code 



ACB4 


60 


RTS 






ACB5 




XPLE 






ACB5 




XPSLE 






ACB5 


2026AD 


JSR 


XCMP 




ACB8 


304B ~AD05 


BMI 


XT RUE 




ACBA 


F049 "AD05 


BEQ 


XTRUE 




ACBC 


1042 "AD00 


BPL 


XFALSE 




ACBE 




XPNE 






ACBE 




XPSNE 






ACBE 


2026AD 


JSR 


XCMP 




ACC1 


F03D "AD00 


BEQ 


XFALSE 




ACC3 


D040 "AD05 


BNE 


XTRUE 




ACC5 




XPLT 






ACC5 




XPSLT 






ACC5 


2026AD 


JSR 


XCMP 




ACC8 


303B "AD05 


BMI 


XTRUE 




ACCA 


1034 "AD00 


BPL 


XFALSE 




ACCC 




XPGT 






ACCC 




XPSGT 






ACCC 


2026AD 


JSR 


XCMP 




ACCF 


302F "AD00 


BMI 


XFALSE 




ACD1 


F02D ~AD00 


BEQ 


XFALSE 




ACD3 


1030 ~AD05 


BPL 


XTRUE 




ACD5 




XPGE 






ACD5 




XPSGE 






ACD5 


2026AD 


JSR 


XCMP 




ACD8 


3026 "AD00 


BMI 


XFALSE 




AC DA 


1029 "AD05 


BPL 


XTRUE 




AC DC 




XPEQ 






AC DC 




XPSEQ 






AC DC 


2026AD 


JSR 


XCMP 




AC DP 


F024 "AD05 


BEQ 


XTRUE 




ACE1 


D01D "AD00 


BNE 


XFALSE 




ACE 3 




XPAND 






ACE 3 


2006AC 


JSR 


ARGP2 




ACE6 


A5D4 


LDA 


FR0 




ACE 8 


25E0 


AND 


FR1 




ACEA 


F014 "AD00 


BEQ 


XFALSE 




ACEC 


D017 "AD05 


BNE 


XTRUE 




ACEE 




XPOR 






ACEE 


2006AC 


JSR 


ARGP2 




ACF1 


A5D4 


LDA 


FR0 




ACF3 


05E0 


ORA 


FR1 




ACF5 


F009 "AD00 


BEQ 


XFALSE 




ACF7 


D00C "AD05 


BNE 


XTRUE 




ACF9 




XPNOT 






ACF9 


20F2AB 


JSR 


ARGPOP 




ACFC 


A5D4 


LDA 


FR0 




ACFE 


F005 ~AD05 


BEQ 


XTRUE 
FALL THROUGH TO 


XFALSE 


AD00 




XFALSE 






AD00 


A900 


LDA 


#0 




AD02 


A8 


TAY 






AD03 


F004 ~AD09 


BEQ 


XTF 




AD05 




XT RUE 






AD05 


A940 


LDA 


#$40 




AD07 




XTI 






AD07 


A001 


LDY 


#1 




AD09 




XTF 






AD09 


85D4 


STA 


FR0 




AD0B 


84D5 


STY 


FR0+1 




AD0D 


A2D6 


LDX 


#FR0+2 


; 


AD0F 


A004 


LDY 


#FPREC-2 


; 1 


AD11 


2048DA 


JSR 


ZXLY 


; 


AD14 


85D2 


STA 


VTYPE 




AD16 




XPUSH 






AD16 


4CBAAB 


JMP 


ARGPUSH 





POINT TO PART TO CLEAR 
GET # OF BYTES TO CLEAR 
CLEAR REST OF FR0 



195 



Source Code 



XPSGN — Sign Function 



AD19 




XPSGN 




AD19 


20F2AB 


JSR 


ARGPOP 


AD1C 


A5D4 


LDA 


FR0 


AD1E 


F0F6 *AD16 


BEQ 


XPUSH 


AD20 


10E3 "AD05 


BPL 


XT RUE 


AD22 


A9C0 


LDA 


#$C0 


AD24 


30E1 "AD07 


BMI 


XT I 



; GET MINUS EXPONENT 



XCMP — Compare Executor 



AD26 




XCMP 






AD26 


A4A9 


LDY 




OPSTKX 


AD28 


88 


DEY 






AD29 


B180 


LDA 




[ARGSTK],Y 


AD2B 


C92F 


CMP 




#CSLE 


AD2D 


9003 ~AD32 


BCC 




FRCMPP 


AD2F 


4C81AF 


JMP 




STRCMP 


AD32 


2006AC 


FRCMPP 


JSR 


ARGP2 



GET OPERATOR THAT 
GOT US HERE 

IF OP WAS ARITHMETIC 
THEN DO FP REG COMP 
ELSE DO STRING COMPARE 



FRCMP — Compare Two Floating Point Numbers 

* ON ENTRY FR0 E, FR1 CONTAIN FLOATING POINT #'S 



ON EXIT CC = + FR0 > FR1 
CC = - FR0 < FR1 
CC = FRE0 ■ FR1 



AD35 




FRCMP 




AD35 


2041AD 


JSR 


FRSUB 


AD38 


A5D4 


LDA 


FR0 


AD 3 A 


60 


RTS 





SUBTRACT FR1 FROM FR0 



; GET FR0 EXPONENT 
; RETURN WITH CC SET 



FRADD — Floating Point Add 



DOES NOT RETURN IF ERROR 



AD3B FRADD 

AD3B 2066DA JSR 

AD3E B013 "AD53 BCS 

AD40 60 RTS 



FADD 
:ERROV 



ADD TWO f 
BR IF ERROR 



FRSUB — Floating Point Subtract 

* DOES NOT RETURN IF ERROR 



AD41 FRSUB 

AD41 2060DA JSR 

AD44 B00D "AD53 BCS 

AD46 60 RTS 



FSUB 
:ERROV 



; SUB TWO # 
; BR IF ERROR 



FRMUL — Floating Point Multiply 

* DOES NOT RETURN IF ERROR 



AD47 FRMUL 

AD47 20DBDA JSR 

AD4A B007 "AD53 BCS 

AD4C 60 RTS 



FMUL 
: ERROV 



MULT TWO # 
BR IF ERROR 



FRDIV — Floating Point Divide 



DOES NOT RETURN IF ERROR 



AD4D 

AD4D 2028DB 



FRDIV 

JSR 



DIVIDE TWO # 



196 



Source Code 



AD50 
AD52 



AD53 
AD53 



B001 "AD53 
60 



202AB9 



BCS 
RTS 



ERROV 
JSR 



BR IF ERROR 



CVFPI — Convert Floating Point to Integer 



DOES NOT RETURN IP ERROR 



AD56 


CVFPI 






AD56 


20D2D9 


JSR 


FPI 


; GO CONVERT TO INTEGER 


AD59 


B001 "AD5C 


BCS 


: ERRVAL 


; IF ERROR, BR 


AD5B 


60 


RTS 




; ELSE RETURN 


AD5C 




ERRVAL 






AD5C 


203AB9 


JSR 


ERVAL 


; VALUE ERROR 



XPAASN — Arithmetic Assignment Operator 



AD5F 




XPAASN 




AD5F 


A5A9 


LDA 


OPSTKX 


AD61 


C9FF 


CMP 


#$FF 


AD63 


D00F "AD74 


BNE 


:AAMAT 


AD65 


2006AC 


JSR 


ARGP2 


AD68 


A205 


LDX 


#5 


AD6A 


B5E0 


:AASN1 LDA 


FR1.X 


AD6C 


95D4 


STA 


FR0,X 


AD6E 


CA 


DEX 




AD6F 


10F9 "AD6A 


BPL 


:AASN1 


AD71 


4C16AC 


JMP 


RTNVAR 


AD74 




:AAMAT 




AD74 


A980 


LDA 


#?80 


AD76 


85B1 


STA 


ADFLAG 


AD78 


60 


RTS 





GET OP STACK INDEX 

AT STACK START 

BR IF NOT, [MAT ASSIGN] 

DO SCALER ASSIGN 
GO POP TOP 2 ARGS 
MOVE FR1 VALUE 
TO FR0 



FR0 TO WT & RETURN 



SET ASSIGN FLAG BIT ON 
IN ASSIGN/DIM FLAG 
GO POP REM OFF OPS 



XPACOM — Array Comma Operator 



AD79 




XPACOM 




AD79 


E6B0 


INC 


COMCNT 


XPRPRN - Right 


Parenthesis 


Operator 






■ 


XPFLPRN - 


AD7B 




XPRPRN 




AD7B 




XPFLPRN 




AD7B 


A4A9 


LDY 


OPSTKX 


AD7D 


68 


PLA 




AD7E 


68 


PLA 




AD7F 


4C0BAB 


JMP 


EXOPOP 



INCREMENT COMMA COUNT 



FUNCTION RIGHT PAREN OPERATOR 



; GET OPERATOR STACK TOP 



; GO POP AND EXECUTE NEXT 
OPERATOR 



XPDLPRN — DIM Left Parenthesis Operator 



AD82 




XDPSLP 




AD82 




XPDLPRN 




AD82 


A940 


LDA 


#?40 


AD84 


85B1 


STA 


ADFLAG 



SET DIM FLAG BIT 
IN ADFLAG 

FALL THRU TO XPALPRN 



197 



Source Code 



XPALPRN — Array Left Parenthesis Operator 



AD86 






XPALPRN 




AD86 


24B1 




BIT 


ADFLAG 


AD88 


1006 


"AD90 


BPL 


:ALP1 


AD8A 


A5AA 




LDA 


ARSLVL 


AD8C 


85AF 




STA 


ATEMP 


AD8E 


C6AA 




DEC 


ARSLVL 


AD90 


A900 




:ALP1 LDA #0 


AD92 


A8 




TAY 




AD93 


C5B0 




CMP 


COMCNT 


AD95 


F00B 


"ADA2 


BEQ 


:ALP2 


AD97 


C6B0 




DEC 


COMCNT 


AD99 


20E3AB 


JSR 


GTINTO 


AD9C 


A5D5 




LDA 


FR0+1 


AD9E 


3023 


"ADC3 


BMI 


:ALPER 


ADA0 


A4D4 




LDY 


FR0 



IF NOT ASSIGN 
THE BRANCH 

ELSE 
SAVE STACK LEVEL 
OF THE VALUE ASSIGNMENT 
AND PSEUDO POP IT 

INIT FOR 12 = 

IF COMMA COUNT =0 THEN 
BR WITH 12 = 
ELSE 

ELSE POP 12 AND MAKE INT 

ERROR IF > 32,767 



ADA2 8598 
ADA4 8497 



:ALP2 STA INDEX2+1 
STY INDEX2 



;SET 12 VALUE 



ADA 6 
ADA9 
ADAB 
ADAD 
ADAF 
ADB1 



ADC 6 
ADC6 
ADC8 
ADCA 
ADCC 

ADCE 
ADD0 
ADD 2 

ADD4 
ADD6 
ADD8 
ADDA 
ADDC 
ADDE 
ADE0 



20E3AB 

A5D4 

85F5 

A5D5 

3012 "ADC3 

85F6 



ADB3 20F2AB 

ADB6 24B1 

ADB8 5005 "ADBF 

ADBA A900 

ADBC 85B1 

ADBE 60 

ADBF 

ADBF 66D2 

ADC1 B003 "ADC6 

ADC3 202EB9 



JSR 


GTINTO 


LDA 


FR0 


STA 


ZTEMP1 


LDA 


FR0+1 


BMI 


: ALPER 


STA 


ZTEMP1+1 


JSR 


ARGPOP 


BIT 


ADFLAG 


BVC 


:ALP3 


LDA 


#0 


STA 


ADFLAG 


RTS 





ALP3 

ROR VTYPE 
BCS :ALP4 

ALPER JSR ERRDIM 



A5F6 
C5D7 

9008 "ADD4 
D0F5 "ADC3 

A5F5 
C5D6 
B0EF ~ADC3 



A598 
C5D9 
9008 
D0E7 
A597 
C5D8 
B0E1 



'ADE2 
"ADC 3 



ALP4 
LDA 
CMP 
BCC 
BNE 

LDA 
CMP 
BCS 



CMP 
BCC 
BNE 
LDA 
CMP 
BCS 



ZTEMP1+1 
VTYPE+EVAD1+1 
:ALP5 
: ALPER 

ZTEMP1 
VTYPE+EVAD1 
: ALPER 

INDEX2+1 
VTYPE+EVAD2+1 
:ALP6 
rALPERR 
INDEX2 
VTYPE+EVAD2 
: ALPER 



POP 12 AND MAKE INT 
MOVE II 
TO ZTEMP1 

ERROR IF > 32,767 



POP THE ARRAY ENTRY 

IF NOT EXECUTING DIM 
THEN CONTINUE 
TURN OFF DIM BIT 
IN ADFLAG 
AND RETURN 



IF ARRAY HAS BEEN 
DIMED THEN CONTINUE 
ELSE DIM ERROR 



TEST INDEX 1 
IN RANGE WITH 
DIM1 



TEST INDEX 2 
IN RANGE WITH 
DIM 2 



ADE2 
ADE5 
ADE7 
ADE9 
ADEC 
ADEF 
ADF1 
ADF3 
ADF6 



205DAF 

A597 

A498 

2052AF 

2046AF 

A5D4 

A4D5 

2052AF 

A58C 



LDA 
LDY 
JSR 
JSR 
LDA 
LDY 
JSR 
LDA 



AMUL1 
INDEX2 
INDEX2+1 
AADD 
AMUL2 

VTYPE+EVAADR 
VTYPE+EVAADR+1 
AADD 
STARP 



;INDEX1 a INDEX1 

rINDEXl = INDEX1 + INDEX2 



ZTEMP1 = ZTEMP1*6 
ZTEMP1 = ZTEMP1 + DISPL 



; ZTEMP1 = ZTEMP1 + ADR 



198 



Source Code 



ADF8 


A48D 


ADFA 


2052AF 


ADFD 


24B1 


ADFF 


1015 " 


AE01 


A5AF 


AE03 


85AA 


AE05 


20F2AB 


AE08 


A005 


AE0A 


B9D400 


AE0D 


91F5 


AE0F 


88 


AE10 


10F8 " 


AE12 


C8 


AE13 


84B1 


AE15 


60 


AE16 


A005 


AE18 


B1F5 


AE1A 


99D400 


AE1D 


88 


AE1E 


10F8 " 


AE20 


C8 


AE21 


84D2 


AE23 


4CBAAB 



LDY 




STARP+1 


JSR 




AADD 


BIT 




ADFLAG 


BPL 




:ALP8 


LDA 




ATEMP 


STA 




ARSLVL 


JSR 




ARGPOP 


LDY 




#5 


:ALP7 


LDA 


FR0, Y 


STA 




[ZTEMP1],Y 


DEY 






BPL 




:ALP7 


I NY 






STY 




ADFLAG 


RTS 






:ALP8 


LDY 


#5 


:ALP9 


LDA 


CZTEMP 



STA FR0,Y 

DEY 

BPL :ALP9 



I NY 




STY 


VTYPE 


JMP 


ARGPUSH 



ZTEMP1 NOW POINTS 
TO ELEMENT REQD 

; IF NOT ASSIGN 

; THEN CONTINUE 

ELSE ASSIGN 

; RESTORE ARG LEVEL 

; TO VALUE AND 

1 POP VALUE 



MOVE VALUE 

TO ELEMENT SPACE 



TURN OFF 

ADFLAG 

DONE 



MOVE ELEMENT TO 



FR0 



PUSH FR0 BACK TO STACK 
AND RETURN 



XPSLPRN — String Left Parenthesis 



AE26 






XPSLPRN 






AE26 


A5B0 




LDA 


COMCNT 


IF NO INDEX 2 


AE28 


F007 


"AE31 


BEQ 


:XSLP2 


THEN BR 


AE2A 


2096AE 


JSR 


:XSPV 


ELSE POP 12 AND 


AE2D 


8498 




STY 


INDEX2+1 


SAVE IN INDEX 2 


AE2F 


8597 




STA 


INDEX2 




AE31 


2096AE 


:XSLP2 JSR 


:XSPV 


POP INDEX 1 


AE34 


38 




SEC 




ADD DECREMENT BY ONE 


AE35 


E901 




SBC 


#1 


AND PUT INTO ZTEMP1 


AE37 


85F5 




STA 


ZTEMP1 




AE39 


98 




TYA 






AE3A 


E900 




SBC 


#0 




AE3C 


85F6 




STA 


ZTEMP1+1 




AE3E 


20F2AB 


JSR 


ARGPOP 


POP ARG STRING 


AE41 


A5B1 




LDA 


ADFLAG 


IF NOT A DEST STRING 


AE43 


100B 


"AE50 


BPL 


:XSLP3 


THEN BRANCH 


AE45 


05B0 




ORA 


COMCNT 




AE47 


85B1 




STA 


ADFLAG 




AE49 


A4D9 




LDY 


VTYPE+EVSDIM+1 


INDEX 2 LIMIT 


AE4B 


A5D8 




LDA 


VTYPE+EVSDIM 


IS DIM 


AE4D 


4C54AE 


JMP 


:XSLP4 




AE50 


A5D6 




:XSLP3 LDA 


VTYPE+EVSLEN 


; INDEX 2 LIMIT 


AE52 


A4D7 




LDY 


VTYPE+EVSLEN+1 


IS STRING LENGTH 


AE54 


A6B0 




:XSLP4 LDX 


COMCNT 


IF NO INDEX 2 


AE56 


F010 


"AE68 


BEQ 


:XSLP6 


THEN BRANCH 


AE58 


C6B0 




DEC 


COMCNT 


ELSE 


AE5A 


C498 




CPY 


INDEX2+1 




AE5C 


9035 


~AE93 


BCC 


:XSLER 




AE5E 


D004 


"AE64 


BNE 


:XSLP5 


INDEX 2 LIMIT 


AE60 


C597 




CMP 


INDEX2 




AE62 


902F 


"AE93 


BCC 


:XSLER 





199 



Source Code 



AE64 


A498 




:XSLP5 


LDY 


INDEX2+1 


•USE INDEX 2 


AE66 


A597 




LDA 




INDEX2 


AS LIMIT 


AE68 


38 




XSLP6 


SEC 




• LENGTH IS 


AE69 


E5F5 




SBC 




ZTEMP1 




AE6B 


85D6 




STA 




VTYPE+EVSLEN 


LIMIT - INDEX 1 


AE6D 


AA 




TAX 








AE6E 


98 




TYA 








AE6F 


E5F6 




SBC 




ZTEMP1+1 




AE71 


85D7 




STA 




VTYPE+EVSLEN+1 




AE73 


901E 


~AE93 


BCC 




: XSLER 


LENGTH MUST BE 


AE75 


A8 




TAY 






GE ZERO 


AE76 


D003 


"AE7B 


BNE 




:XSLP7 




AE78 


8A 




TXA 








AE79 


F018 


~AE93 


BEQ 




: XSLER 




AE7B 


209BAB 


XSLP7 


JSR 


GSTRAD 


GET ABS ADR 


AE7E 


18 




CLC 








AE7F 


A5D4 




LDA 




VTYPE+EVSADR 




AE81 


65F5 




ADC 




ZTEMP1 


STRING ADR 


AE83 


85D4 




STA 




VTYPE+EVSADR 


STRING ADR + INDEX 1 


AE85 


A5D5 




LDA 




VTYPE+EVSADR+1 




AE87 


65F6 




ADC 




ZTEMP1+1 




AE89 


85D5 




STA 




VTYPE+EVSADR+1 




AE8B 


24B1 




BIT 




ADFLAG 


IF NOT ASSIGN 


AE8D 


1001 


~AE90 


BPL 




:XSLP8 


THEN BR 


AE8F 


60 




RTS 






ELSE RETURN TO ASSIGN 


AE90 


4CBAAB 


XSLP8 


JMP 


ARGPUSH 


PUSH ARG AND RETURN 


AE93 


2036B9 


XSLER 


JSR 


ERRSSL 




XSPV 


— Pop 


Index Va 


lue as Intege 


r and Insure Not Zero 


AE96 






XSPV 








AE96 


20E3AB 


JSR 




GTINTO 


GO GET THE INTEGER 


AE99 


A5D4 




LDA 




FR0 


GET VALUE LOW 


AE9B 


A4D5 




LDY 




FR0+1 


GET VALUE HI 


AE9D 


D003 


"AEA2 


XSPV1 


BNE 


: XSPVR 


RTN IF VH NOT ZERO 


AE9F 


AA 




TAX 






TEST VL 


AEA0 


F0F1 


"AE93 


BEQ 




: XSLER 


BR VL.VH = 


AEA2 


60 




XSPVR 


RTS 




DONE 



XSAASN — String Assign Operator 



AEA3 




XSAASN 






AEA3 


2098AB 


JSR 


AAPSTR 


; POP STR WITH ABS ADR 


AEA6 




RISASN 






AEA6 


A5D4 


LDA 


VTYPE+EVSADR 


; MVFA = ADR 


AEA8 


8599 


STA 


MVFA 




AEAA 


A5D5 


LDA 


VTYPE+EVSADR+1 




AEAC 


859A 


STA 


MVFA+1 




AEAE 


A5D6 


LDA 


VTYPE+EVSLEN 




AEB0 


85A2 


STA 


MVLNG 


; MVLNG = LENGTH 


AEB2 


A4D7 


LDY 


VTYPE+EVSLEN+1 




AEB4 


84A3 


STY 


MVLNG+1 




AEB6 


A4A9 


LDY 


OPSTKX 


. IF AT T op OF 


AEB8 


C0FF 


CPY 


#SFF 


; OP STACK 


AEBA 


F00F "AECB 


BEQ 


:XSA1 


; THEN BR 
ELSE 


AEBC 


A980 


LDA 


#S80 


; SET ASSIGN BIT 


AEBE 


85B1 


STA 


ADFLAG 


; IN ASSIGN/DIM FLAG 


AEC0 


200BAB 


JSR 


EXOPOP 


; AND PROCESS SUBSTRING 


AEC3 


A5D7 


LDA 


VTYPE+EVSLEN+1 


; A,Y = 


AEC5 


A4D6 


LDY 


VTYPE+EVSLEN 


; DEST LEN 


AEC7 


26B1 


ROL 


ADFLAG 


; TURN OFF ASSIGN 


AEC9 


B007 "AED2 


BCS 


:XSA2A 


; AND BR 



200 



Source Code 



AECB 


2098AB 


AECE 


A5D9 


AED0 


A4D8 


AED2 




AED2 


C5A3 


AED4 


9006 "AEDC 


AED6 


D008 "AEE0 


AED8 


C4A2 


AEDA 


B004 "AEE0 


AEDC 


85A3 


AEDE 


84 A 2 


AEE0 


18 


AEE1 


A5D4 


AEE3 


65A2 


AEE5 


A8 


AEE6 


A5D5 


AEE8 


65A3 


AEEA 


AA 


AEEB 


38 


AEEC 


98 


AEED 


E58C 


AEEP 


85F9 


AEF1 


8A 


AEF2 


E58D 


AEF4 


85FA 


AEF6 


38 


AEF7 


A900 


AEF9 


E5A2 


AEFB 


85A2 


AEFD 


38 


AEFE 


A599 


AF00 


E5A2 


AF02 


8599 


AF04 


A59A 


AF06 


E900 


AF08 


859A 


AF0A 


38 


AF0B 


A5D4 


AF0D 


E5A2 


AF0F 


859B 


AF11 


A5D5 


AF13 


E900 


AF15 


859C 



POP STR WITH ABS ADR 



LDY 



VTYPE+EVSDIM+1 
VTYPE+EVSDIM 



A,Y = DEST LENGTH 



:XSA2A 

CMP MVLNG+1 

BCC :XSA3 

BNE :XSA4 

CPY MVLNG 

BCS :XSA4 
:XSA3 STA MVLNG+1 

STY MVLNG 



AF17 2047A9 



AF1A 


A5D3 


AF1C 


2089AB 


AF1F 


38 


AF20 


A5F9 


AF22 


E5D4 


AF24 


A8 


AF25 


A5FA 


AF27 


E5D5 


AF29 


AA 



:XSA4 



CLC 



AF2A A902 

AF2C 25B1 

AF2E F00F "AF3F 

AF30 A900 



LDA 


VTYPE+EVSADR ; 


ADC 


MVLNG ; 


TAY 




LDA 


VTYPE+EVSADR+1 


ADC 


MVLNG+1 


TAX 




SEC 




TYA 




SBC 


STARP ; 


STA 


ZTEMP3 ; 


TXA 




SBC 


STARP+1 ; 


STA 


ZTEMP3+1 


SEC 




LDA 


#0 ; 


SBC 


MVLNG ; 


STA 


MVLNG ; 


SEC 




LDA 


MVFA 


SBC 


MVLNG ; 


STA 


MVFA ; 


LDA 


MVFA+1 


SBC 


#0 


STA 


MVFA+1 


SEC 




LDA 


VTYPE+EVSADR 


SBC 


MVLNG ; 


STA 


MVTA 


LDA 


VTYPE+EVSADR+1 ; 


SBC 


#0 ; 


STA 


MVTA+1 


JSR 


FMOVER ;< 


LDA 


VNUM ; 


JSR 


GETVAR ; 


SEC 


. 


LDA 


ZTEMP3 ; 


SBC 


VTYPE+EVSADR 


TAY 




LDA 


ZTEMP3+1 


SBC 


VTYPE+EVSADR+1 


TAX 




LDA 


#02 


AND 


ADFLAG ; 


BEQ 


: XSA5 


LDA 


#0 ; 



IF DEST LENGTH 

LESS THAN MOVE LENGTH 



SET MOVE LENGTH 
= DIST LENGTH 



MOVE LENGTH PLUS 
START ADR IS 
END ADR 



END ADR MINUS 
START OF STRING 
SPACE IS DISPL 
TO END OF STRING 
WHICH WE SAVE 
IN ZTEMP3 



SET MOVE LENGTH LOW 
= $100 - MVL [L] 
BECAUSE OF THE WAY 
FMOVE WORKS 



ADJUST MVFA TO 
CONFORM WITH MVL 
CHANGE 



MOVE THE DEST 
STRING ADR TO 
MVTA AND 
MAKE IT CONFORM 
WITH MVL 



GO DO THE VERY FAST MOVE 



GO GET ORIGNAL DEST 
STRING 

DISPL TO END OF 
MOVE MINUS DISPL 
TO START OF STRING 
IS OUR RESULT LENGTH 



IF THE DESTINATION 
LENGTH WAS IMPLICT 
SET NEW LENGTH 
CLEAR 



201 



Source Code 



AF32 85B1 



AF34 


E4D7 




AF36 


9006 


~AF3E 


AF38 


D005 


"AF3F 


AF3A 


C4D6 




AF3C 


B001 


"AF3F 


AF3E 


60 




AF3F 


84D6 




AF41 


86D7 




AF43 


4C16AC 



STA 


ADFLAG 


; FLAG 

ELSE FOR EXPLICT LENGTH 


CPX 


VTYPE+EVSLEN+1 


; IF NEW LENGTH 


BCC 


:XSA6 


; GREATER THAN 


BNE 


:XSA5 


; OLD LENGTH THEN 


CPY 


VTYPE+EVSLEN 


; SET NEW LENGTH 


BCS 


:XSA5 


; ELSE DO NOTHING 



:XSA6 



RTS 



:XSA5 STY VTYPE+EVSLEN 
STX VTYPE+EVSLEN+1 
JMP RTNVAR 



AMUL2 — Integer Multiplication of ZTEMP1 by 6 



AF46 






AMUL2 








AF46 


06F5 




ASL 




ZTEMP1 


• ZTEMP1 = ZTEMP1*2 


AF48 


26F6 




ROL 




ZTEMP1+1 




AF4A 


A4F6 




LDY 




ZTEMP1+1 


; SAVE ZTEMP1*2 IN [A,Y] 


AF4C 


A5F5 




LDA 




ZTEMP1 




AF4E 


06F5 




ASL 




ZTEMP1 


; ZTEMP1 = ZTEMP1*4 


AF50 


26F6 




ROL 




ZTEMP1+1 




AADD 


— Integer Addition of [A,Y] to ZTEMP1 




AF52 






AADD 








AF52 


18 




CLC 








AF53 


65F5 




ADC 


ADC 


ZTEMP1 


; ADD LOW ORDER 


AF55 


85F5 




STA 




ZTEMP1 




AF57 


98 




TYA 








AF58 


65F6 




ADC 




ZTEMP1+1 


; ADD HIGH ORDER 


AF5A 


85F6 




STA 




ZTEMP1+1 




AF5C 


60 




RTS 






; DONE 


AMUl 


— Integer Multiplication of ZTEMP1 by DIM2 




AF5D 






AHUL1 








AF5D 


A900 




LDA 




#0 


■ CLEAR PARTIAL PRODUCT 


AF5F 


85F7 




STA 




ZTEMP4 




AF61 


85F8 




STA 




ZTEMP4+1 




AF63 


A010 




LDY 




#510 


■ SET FOR 16 BITS 


AF65 


A5F5 




:AM1 


LDA 


ZTEMP1 


• GET MULTIPLICAN 


AF67 






LSRA 






■ TEST MSB = ON 


AF67 


+4A 




LSR 




A 




AF68 


900C 


"AF76 


BCC 




:AM3 


- BR IF OFF 


AF6A 


18 




CLC 








AF6B 


A2FE 




LDX 




#$FE 


; ADD MULTIPLIER 


AF6D 


B5F9 




:AM2 


LDA 


ZTEMP4+2.X 


; TO PARTIAL PRODUCT 


AF6F 


75DA 




ADC 




VTYPE+EVAD2+2.X 




AF71 


95F9 




STA 




ZTEMP4+2.X 




AF73 


E8 




I NX 








AF74 


D0F7 


"AF6D 


BNE 




:AM2 




AF76 


A203 




:AM3 


LDX 


#3 


| MULT PRODUCT BY 2 


AF78 


76F5 




:AM4 


ROR 


ZTEMP1.X 




AF7A 


CA 




DEX 








AF7B 


10FB 


"AF78 


BPL 




:AM4 




AF7D 


88 




DEY 






; TEST MORE BITS 


AF7E 


D0E5 


~AF65 


BNE 




:AM1 


,- BR IF MORE 



STRCMP — String Compare 



AF81 




STRCMP 




AF81 


2098AB 


JSR 


AAPSTR 


AF84 


20B6DD 


JSR 


MV0TO1 


AF87 


2098AB 


JSR 


AAPSTR 



POP STRING WITH ABS ADR 

MOVE B TO FR1 

POP STRING WITH ABS ADR 



202 



Source Code 



AF8A 
AF8C 
AF8P 
AF90 
AF92 
AF95 
AF97 
AF98 



A2D6 

20BCAP 

08 

A2E2 

20BCAF 

F013 "AFAA 

28 

F00D "AFA7 



IFR0-2+EVSLEN 



JSR 
PHP 
LDX 
JSR 
BEQ 
PLP 
BEQ 



ZPADEC 

#FRl-2+EVSLEN 

ZPADEC 

:SC2 

:SCLT 



GO DEC STR A LEN 

SAVE RTN CODE 
GO DEC STR B LEN 

BR STR B LEN = 
GET STR A COND CODE 
BR STR A LEN = 



AF9A A000 LDY #0 ; 

AF9C B1D4 LDA [FR0-2+EVSADR] , Y 

AF9E D1E0 CMP [FR1-2+EVSADR] , Y 

AFA0 F00C ~AFAE BEQ :SC3 ; 

AFA2 9003 "AFA7 BCC :SCLT ; 



COMPARE A BYTE 
; OF STRING A 
; TO STRING B 

BR IF SAME 

BR IF A<B 



AFA4 A901 
AFA6 60 



:SCGT LDA 
RTS 



SI 



A>B 



AFA7 A980 
AFA9 60 



:SCLT LDA 
RTS 



#$80 



AFAA 28 



AFAB 
AFAD 
AFAE 
AFB0 
AFB2 
AFB4 
AFB6 
AFB8 
AFBA 



D0F7 "AFA4 

60 

E6D4 

D002 ~AFB4 

E6D5 

E6E0 

D0D2 ~AF8A 

E6E1 

D0CE "AF8A 



:SC2 

BNE 

:SCEQ 

:SC3 

BNE 
INC 

:SC4 

BNE 
INC 
BNE 



RTS 
INC 



:SCGT 

FR0-2+EVSADR 
:SC4 
FR0-1+EVSADR 

FR1-2+EVSADR 
!SC1 

FR1-1+EVSADR 
:SC1 



ZPADEC — Decrement a Zero-Page Double Word 



AFBC 
AFBC 
AFBE 
AFC0 
AFC 2 
AFC 4 
AFC 6 
AFC8 
AFC 9 



B500 

D006 

B501 

F005 

D601 

D600 

A8 

60 



'AFC 9 



ZPADEC 

LDA 

BNE 

LDA 

BEQ 

DEC 
:ZPAD1 DEC 

TAY 
:ZPADR RTS 



0,X 

:ZPAD1 

1,X 

:ZPADR 

1,X 

0,X 



IF STR A LEN NOT 
ZERO THEN A>B 
ELSE A=B 

; INC STR A ADR 



INC STR B ADR 



GET LOW BYTE 
BR NOT ZERO 
GET HI BYTE 
BR IF ZERO 
DEC HIGH BYTE 
DEC LOW BYTE 
SET NE COND CODE 
RETURN 



Functions 



XPLEN — Length Function 



AFCA 




XPLEN 






AFCA 


2098AB 


JSR 


AAPSTR 


POP STRING WITH ABS ADR 


AFCD 


A5D6 


LDA 


VTYPE+EVSLEN 


MOVE LENGTH 


AFCF 


A4D7 


LDY 


VTYPE+EVSLEN+1 




AFD1 




XPIFP 






AFD1 


85D4 


STA 


FR0 


TO TOP OF FR0 


AFD3 


84D5 


STY 


FR0+1 




AFD5 


20AAD9 


XPIFP1 JSR 


CVIFP 


AND CONVERT TO FP 


AFD8 




XPIFP2 






AFD8 


A900 


LDA 


#0 


CLEAR 


AFDA 


85D2 


STA 


VTYPE 


TYPE AND 


AFDC 


85D3 


STA 


VNUM 


NUMBER 


AFDE 


4CBAAB 


JMP 


ARGPUSH 


PUSH TO STACK AND RETURN 


XPPEI 


K — PEEK Function 






AFEl 




XPPEEK 






AFE1 


20E3AB 


JSR 


GTINTO 


• GET INT ARG 


AFE4 


A000 


LDY 


#0 




AFE6 


B1D4 


LDA 


[FR0],Y 


• GET MEM BYTE 


AFE8 


4CD1AF 


JMP 


XPIFP 


• GO PUSH AS FP 



203 



Source Code 



XPFRE — FRE Function 



AFEB 




XPFRE 






AFEB 


20F2AB 


JSR 


ARGPOP 


; POP DUMMY ARG 


AFEE 


38 


SEC 






AFEF 


ADE502 


LDA 


HIMEM 


; NO FREE BYTES 


AFF2 


E590 


SBC 


MEMTOP 


; = HIMEM-MEMTOP 


AFF4 


85D4 


STA 


FR0 




AFF6 


ADE602 


LDA 


HIMEM+1 




AFF9 


E591 


SBC 


MEMTOP+1 




AFFB 


85D5 


STA 


FR0+1 




AFFD 


4CD5AF 


JMP 


XPIFP1 


; GO PUSH AS FP 



XPVAL — VAL Function 



B000 


XPVAL 




B000 


2079BD 


JSR 


SETSEOL ; 


B003 


A900 


LDA 


#0 ; 


B005 


85F2 


STA 


CIX ; 


B007 


2000D8 


JSR 


CVAFP f 


Restore Character 






B00A 


2099BD 


JSR 


RSTSEOL ; 


B00D 


90C9 "AFD8 


BCC 


XPIFP2 


B00F 


':VERR 




B00F 


201CB9 


JSR 


ERSVAL 


XPASC — ASC Function 






B012 


XPASC 




B012 


2098AB 


JSR 


AAPSTR 



Get 1>T Byte of String 



B015 A000 
B017 B1D4 



B019 4CD1AF 



LDY 
LDA 



PUT EOL AT STR END 

GET NUMERIC TERMINATOR 
SET INDEX INTO BUFFER = 
CONVERT TO F.P. 



RESET END OF STR 



GET STRING ELEMENT 



#0 ; GET INDEX TO 1ST BYTE 

[FR0-2+EVSADR],Y ; GET BYTE 



B01C 




XPADR 






B01C 


2098AB 


JSR 


AAPSTR 


;GET STRING 


B01F 


4CD5AF 


JMP 


XPIFP1 


| FINISH 



XPPDL — Function Paddle 

B022 XPPDL 

B022 A900 LDA 

B024 F00A ~B030 BEQ 

XPSTICK — Function Joystick 



B026 

B026 A908 

B028 D006 



XPSTICK 
LDA 
BNE 



#0 
:GRF 



#8 
:GRF 



XPPTRIG — Function Paddle Trigger 

B02A XPPTRIG 

B02A A90C LDA #$0C 

B02C D002 "B030 BNE :GRF 



XPSTRIG — Function Joystick Trigger 

#514 



B02E 

B02E A914 



XPSTRIG 
LDA 



GET DISPL FROM BASE ADDR 



; GET DISP FROM BASE ADDR 



; GET DISPL FROM BASE ADDR 



GET DISP FROM BASE ADDR 



204 



Source Code 



B030 




:GRP 




B030 


48 


PHA 




B031 


20E3AB 


JSR 


GTINTO 


B034 


A5D5 


LDA 


PR0+1 


B036 


D00E "B046 


BNE 


:ERGRP 


B038 


A5D4 


LDA 


FR0 


B03A 


68 


PLA 




B03B 


18 


CLC 




B03C 


65D4 


ADC 


FR0 


B03E 


AA 


TAX 




B03F 


BD7002 


LDA 


GRFBAS.X 


B042 


A000 


LDY 


#0 


B044 


F08B "AFD1 


BEQ 


XPIFP 



B046 

B046 203AB9 



ERGRF 
JSR 



GET INTEGER FROM STACK 
HIGH ORDER BYTE 
SHOULD BE =0 
GET # 

GET DISPL FROM BASE 

ADD MORE DISPL 

GET VALUE 

GO CONVERT & PUSH ON STACK 



ERVAL 



XPSTR — STR Function 

B049 XPSTR 

B049 20F2AB JSR 

B04C 20E6D8 JSR 

Build String Element 

B04F A5F3 LDA 

B051 85D4 STA 

B053 ASF4 LDA 

B055 85D5 STA 



Get Length 

B057 A0FF 
B059 

B059 C8 

B05A B1F3 



B05C 
B05E 
B060 
B062 



10FB 
297F 
91F3 
C8 



LDY 
:XSTR1 
INY 
LDA 
"B059 BPL 
AND 
STA 
INY 



B063 84D6 



STY 



ARGPOP 
CVFASC 



INBUFF 

FR0-2+EVSADR 
INBUFF+1 
FR0-1+EVSADR 



B065 D017 B07E 



#SFF 



[INBUFF], Y 
:XSTR1 
#?7F 
ClNBUFF], Y 



FR0-2+EVSLEN 
:CHR 



GET VALUE IN FR0 
CONVERT TO ASCII 



INIT FOR LENGTH COUNTER 

BUMP COUNT 

GET CHAR 

IS MSB NOT ON, REPEAT 

TURN OFF MSB 

RETURNS CHAR TO BUFFER 

INC TO GET LENGTH 

SET LENGTH LOW 

JOIN CHR FUNCTION 



XPCHR-CHR Function 



B067 
B067 


20F2AB 


B06A 
B06D 
B06F 


2056AD 

A5D4 

8DC005 


Build 


String Eli 


B072 
B074 
B076 
B078 


A905 
85D5 
A9C0 
8SD4 


B07A 
B07C 


A901 
85D6 


B07E 
B080 


A900 
85D7 



XPCHR 

JSR 

JSR 
LDA 
STA 



LDA 
STA 
LDA 
STA 

LDA 
STA 

LDA 
STA 



ARGPOP 

CVFPI 

FR0 

LBUFF+$40 



GET VALUE IN FR0 

CONVERT TO INTEGER 
GET INTEGER LOW 
SAVE 



#(LBUFF+$40)/256 ; SET ADDR 

FR0-1+EVSADR ; X 

#(LBUFF+$40)S,255 ; X 

FR0-2+EVSADR ; X 



#1 
FR0-2+EVSLEN 



#0 
FR0-I+EVSLEN 



SET LENGTH LOW 



SET LENGTH HIGH 
X 



205 



Source Code 



B082 85D3 
B084 A983 
B086 85D2 



STA VNUM r CLEAR VARIABLE # 

LDA #EVSTR+EVSDTA+EVDIM ; GET TYPE FLAGS 
STA VTYPE ; SET VARIABLE TYPE 



B088 4CBAAB 



JMP 



XPRND — RND Function 



B08B 




B08B 


A2A8 


B08D 


A0B0 


B08P 


2098DD 


B092 


20F2AB 


B095 


AC0AD2 


B098 


84D4 


B09A 


AC0AD2 


B09D 


84D5 


B09F 


20AAD9 


B0A2 


204DAD 


B0A5 


4CBAAB 



B0A8 



4206553600 
00 



XPRND 

LDX 
LDY 
JSR 

JSR 

LDY 

STY 
LDY 
STY 
JSR 
JSR 

JMP 



RNDDIV DB 



ARGPUSH 



IRNDDIVS.255 
#RNDDIV/256 
FLD1R 

ARGPOP 

RNDLOC 

FR0 

RNDLOC 

FR0+1 

CVIFP 

FRDIV 



B0AE 
B0AE 
B0B1 
B0B3 
B0B5 
B0B7 



20F2AB 

A5D4 

297F 

85D4 

4CBAAB 



XPABS 

JSR 
LDA 
AND 
STA 
JMP 



XPABS — Absolute Value Function 



XPUSR — USR Function 



B0BA 

B0BA 20C3B0 

B0BD 20AAD9 

B0C0 4CBAAB 



B0C3 

B0C3 A5B0 

B0C5 85C6 

B0C7 

B0C7 20E3AB 

B0CA C6C6 

B0CC 3009 "B0D7 

B0CE A5D4 

B0D0 48 



A5D5 

48 

4CC7B0 



B0D1 

B0D3 

B0D4 

B0D7 

B0D7 A5B0 

B0D9 48 

B0DA 6CD400 



XPUSR 

JSR 
JSR 
JMP 



LDA 
STA 

:USR1 

JSR 
DEC 
BMI 

LDA 
PHA 
LDA 
PHA 
JMP 
:USR2 

LDA 
PHA 
JMP 



XPINT — Integer Function 



B0DD 

B0DD 20F2AB 

B0E0 20E6B0 

B0E3 4CBAAB 



XPINT 

JSR 
JSR 
JMP 



PUSH ON STACK 



POINT TO 65535 
X 
MOVE IT TO FR1 

CLEAR DUMMY ARG 

GET 2 BYTE RANDOM # 
X 
X 
X 

CONVERT TO INTEGER 
DO DIVIDE 

PUT ON STACK 



$42, $06, 555, $36,0,0 



ARGPOP 

FR0 

#$7F 

FR0 

ARGPUSH 



:USR 

CVIFP 

ARGPUSH 



COMCNT 
2TEMP2 



GTINTO 
ZTEMP2 
:USR2 

FR0 

FR0+1 

:USR1 

COMCNT 

[FR0] 



ARGPOP 

XINT 

ARGPUSH 



GET ARGUMENT 

GET BYTE WITH SIGN 

AND OUT SIGN 

SAVE 

PUSH ON STACK 



PUT RETURN ADDR IN CPU STACK 
CONVERT FR0 TO FP 
PUSH ON STACK 



;GET COMMA COUNT 
;SET AS # OF ARG FOR LOOP 
CONTROL 

; GET AN INTEGER FROM OP STACK 

,-DECR # OF ARGUMENTS 

;IF DONE THEM ALL, BRANCH 

GET ARGUMENT LOW 
PUSH ON STACK 
GET ARGUMENT HIGH 
PUSH ON STACK 
GET NEXT ARGUMENT 

GET f OF ARGUMENTS 
PUSH ON CPU STACK 
GO TO USER ROUTINE 



GET NUMBER 

GET INTEGER 

PUSH ON ARGUMENT STACK 



206 



Source Code 



XINT — Take Integer Part of FRO 



B0E6 






XINT 




B0E6 


A5D4 




LDA 


FR0 


B0E8 


297F 




AND 


#$7F 


B0EA 


38 




SEC 




B0EB 


E93F 




SBC 


#$3F 


B0ED 


1002 


"B0F1 


BPL 


:XINT1 ; 


B0EF 


A900 




LDA 


#0 ; 


B0F1 






:XINT1 




B0F1 


AA 




TAX 




B0F2 


A900 




LDA 


*0 ; 


B0F4 


A8 




TAY 




B0F5 






:INT2 




B0F5 


E005 




CPX 


IFMPREC ; 


B0F7 


B007 


"B100 


BCS 


:XINT3 ; 


B0F9 


15D5 




ORA 


FR0M,X ; 


B0FB 


94D5 




STY 


FR0M,X ; 


B0FD 


E8 




I NX 




B0FE 


D0F5 


"B0F5 


BNE 


:INT2 


B100 






:X1NT3 




B100 


A6D4 




LDX 


FR0 ; 


B102 


1014 


"B118 


BPL 


:XINT4 f 


B104 


AA 




TAX 


> 


B105 


F011 


"B118 


BEQ 


:XINT4 ; 



GET EXPONENT 
AND OUT SIGN BIT 

GET LOCATION OF 1ST FRACTION 

BYTE 

IF > OR = 0, THEN BRANCH 

ELSE SET =0 



PUT IN X AS INDEX INTO FR0 
SET ACCUM TO ZERO FOR ORING 
ZERO Y 

IS D.P. LOC > OF = 57 

IF YES, LOOP DONE 

OR IN THE BYTE 

ZERO BYTE 

POINT TO NEXT BYTE 

UNCONDITIONAL BRANCH 



GET EXPONENT 

BR IF # IS PLUS 

GET TOTAL OF ORED BYTES S, 

SET CC 

IF ALL BYTES WERE ZERO 

BRANCH 



# IS NEGATIVE AND NOT A WHOLE # CADD -1] 



B107 


A2E0 


LDX 


#FR1 


B109 


2046DA 


JSR 


ZF1 


B10C 


A9C0 


LDA 


#$C0 


B10E 


85E0 


STA 


FR1 


B110 


A901 


LDA 


#1 


B112 


85E1 


STA 


FR1+1 


B114 


203BAD 


JSR 


FRADD 


B117 


60 


RTS 




B118 




:XINT4 




B118 


4C00DC 


JMP 


NORM 



ZERO 


FI 


a 




PUT 


-1 


IN 


FRl 


X 








X 








X 








ADD 


IT 







; GO NORMALIZE 



Transcendental Functions 



XPSIN — Sine Function 



BUB 




XPSIN 




B11B 


20F2AB 


JSR 


ARGPOP 


B11E 


20A7BD 


JSR 


SIN 


B121 


B03F "B162 


BCS 


:TBAD 


B123 


903A ~B15F 


BCC 


:TGOOD 


XPCOS — Cosine Function 




B125 




XPCOS 




B125 


20F2AB 


JSR 


ARGPOP 


B128 


20B1BD 


JSR 


COS 


B12B 


B035 "B162 


BCS 


:TBAD 


B12D 


9030 "B15F 


BCC 


:TGOOD 


XPATN — Arc Tangent Function 




B12F 




XPATN 




B12F 


20F2AB 


JSR 


ARGPOP 


B132 


2077BE 


JSR 


ATAN 


B135 


B02B "B162 


BCS 


:TBAD 


B137 


9026 "B15F 


BCC 


:TGOOD 



;GET ARGUMENT 



;GET ARGUMENT 



207 



Source Code 



XPLOG — LOG Function 



B139 




XPLOG 




B139 


20F2AB 




JSR 


ARGPOP 


B13C 


20CDDE 




JSR 


LOG 


B13F 


B021 "B162 




BCS 


:TBAD 


B141 


901C "B15F 




BCC 


:TGOOD 


XP4-1C 


— LOG Base 10 






B143 




XPL10 




B143 


20F2AB 




JSR 


ARGPOP 


B146 


20D1DE 




JSR 


LOG 10 


B149 


B017 ~B162 




BCS 


:TBAD 


B14B 


9012 "B15F 




BCC 


:TGOOD 


XPEXI 


» — EXP Function 






B14D 




XPEXP 




B14D 


20F2AB 




JSR 


ARGPOP 


B150 


20C0DD 




JSR 


EXP 


B153 


B00D "B162 




BCS 


:TBAD 


B155 


9008 "B15F 




BCC 


:TGOOD 



XPSQR — Square Root Function 

B157 XPSQR 

B157 20F2AB JSR 

B15A 20E5BE JSR 

B15D B003 "B162 BCS 



ARGPOP 

SQR 

:TBAD 



FALL THREE TO :TGOOD 



B15F 






B15F 


4CBAAB 


B162 






B162 


203AB9 


XPPOWER- 


Expo 


B165 






B165 


2006AC 


B168 


A5D4 




B16A 


D00B 


~B177 


B16C 


A5E0 




B16E 


F004 


"B174 


B170 


10ED 


"B15F 


B172 


30EE 


"B162 


B174 






B174 


4C05AD 


B177 






B177 


1030 


"B1A9 


B179 


297F 




B17B 


85D4 




B17D 


A5E0 




B17F 


297F 




B181 


38 




B182 


E940 




B184 


30DC 


"B162 


B186 


A206 




B188 


C905 




B18A 


9004 


"B190 


B18C 


A001 




B18E 


D008 


"B198 


B190 







:TGOOD 
JMP 



B190 85F5 



:TBAD 






JSR 


ERVAL 


;ntij 


1 Operator [A* *B] 


XPPOWER 






JSR 


ARGP2 




LDA 


FR0 




BNE 


:N0 




LDA 


FR1 




BEQ 


:P0 




BPL 


:TGOOD 




BM1 


:TBAD 


:P0 








JMP 


XTRUE 


:N0 








BPL 


:SPEVEN 




AND 


#$7F 




STA 


FR0 




LDA 


FR1 




AND 


#$7F 




SEC 






SBC 


#?40 




BMI 


:TBAD 




LDX 


#6 


' 


CMP 


#5 




BCC 


:SP4 




LDY 


#1 




BNE 


:SP3 


:SP4 




' 


STA 


ZTEMP1 



;PUSH ARGUMENT ON STACK 



;GET ARGUMENT IN FR0,FR1 
;IS BASE = ? 
;IF BASE NOT 0, BRANCH 
;TEST EXPONENT 



rIF = 

;IF >0, 



; BRANCH 
ANSWER = 
VALUE ERROR 



;IF =0, ANSWER 



IF BASE + THEN NO SPECIAL 

PROCESS 

AND OUT SIGN BIT 

SET AS BASE EXPONENT 

GET EXPONENT OF POWER 
AND OUT SIGN BIT 

IS POWER <1? 
IF YES, ERROR 

GET INDEX TO LAST DIGIT 

IF # CAN HAVE DECIMAL 
PORTION, THEN BR 



SAVE EXP -40 



208 



Source Code 



B192 


38 




SEC 




B193 


A905 




LDA 


#5 


B195 


E5F5 




SBC 


ZTEMP1 


B197 


A8 




TAY 




B198 






:SP3 




B198 


CA 




DEX 




B199 


88 




DEY 




B19A 


F006 


"B1A2 


BEQ 


:SP2 


B19C 


B5E0 




LDA 


FR1,X 


B19E 


D0C2 


"B162 


BNE 


:TBAD 


B1A0 


F0F6 


"B198 


BEQ 


:SP3 


B1A2 






:SP2 




B1A2 


A080 




LDY 


#$80 


B1A4 


B5E0 




LDA 


FR1.X 


B1A6 






LSRA 




B1A6 


+4A 




LSR 


A 


B1A7 


B002 


"B1AB 


BCS 


:POWR 


B1A9 






:SPEVEN 




B1A9 


A000 




LDY 


#0 


B1AB 






:POWR 




B1AB 


9G 




TYA 




B1AC 


48 




PHA 




Save Exponent [from 


FR1] 




B1AD 


A205 




LDX 


#FMPREC 


B1AF 






:P0WR1 




B1AF 


B5E0 




LDA 


FR1.X 


B1B1 


48 




PHA 




B1B2 


CA 




DEX 




B1B3 


10FA 


"B1AF 


BPL 


:P0WR1 


B1B5 


20D1DE 


JSR 


LOG 10 


B1B8 


B0A8 


"B162 


BCS 


:TBAD 



Pull Exponent into FR1 [from CPU Stack] 



B1BA 
B1BC 
B1BE 
B1BE 
B1BF 
B1C1 
B1C2 
B1C3 



A200 
A005 

68 

95E0 

E8 

88 

10F9 "B1BE 



LDX 
LDY 
: P0WR2 
PLA 

STA 
INX 
DEY 
BPL 



#0 
#FMPREC 



;DEC COUNTER 
:P0WR2 



;GET # BYTES POSSIBLE 

; GET # BYTES THAT COULD BE 

DECIMAL 
; SET COUNTER 



DEC COUNTER 

IF DONE GO TEST EVEN/ODD 
GET BYTE OF EXPONENT 
IF NOT =0, THEN VALUE ERROR 
REPEAT 



,- GET ODD FLAG 

;GET BYTE OF EXPONENT 

; IS IT ODD[LAST BIT OFF]? 

; IF YES, BR 



;GET POINTER INTO FR1 

; GET A BYTE 
,-PUSH ON CPU STACK 
.-POINT TO NEXT BYTE 
;BR IF MORE TO DO 

;TAKE LOG OF BASE 



;GET POINTER INTO FR1 
;SET COUNTER 



j PUT IN FR1 
;INCR POINTER 



;BR IF MORE TO DO 



B1C5 2047AD JSR FRMUL 

B1C8 20CCDD JSR EXP10 

B1CB B009 "B1D6 BCS :EROV 



;GET LOG OF NUMBER 
;GET NUMBER 



B1CD 
BICE 



68 

108F 



'B15F 



PLA 
BPL 



:TGOOD 



GET EVEN/ODD FLAG 

IF EVEN, GO PUT ON STACK 



B1D0 05D4 ORA FR0 

B1D2 85D4 STA FR0 

B1D4 D089 "B15F BNE :TGOOD 



IF ODD MAKE ANSWER- 

X 

PUSH ON STACK 



B1D6 
B1D6 



:EROV 

JSR 



209 



Source Code 



Statements 



XDIM & XCOM - Execute DIM and COMMON Statements 



B1D9 






XDIM 








B1D9 






XCOM 








B1D9 


A4A8 




:DC1 


LDY 


STINDEX 


• IF NOT AT 


B1DB 


C4A7 




CPY 




NXTSTD 


■ STATEMENT END 


B1DD 


9001 " 


B1E0 


BCC 




:DC2 


■ THEN CONTINUE 


B1DP 


60 




RTS 






■ RETURN 


B1E0 


20E0AA 




:DC2 


JSR 


EXEXPR 


■ GO SET UP VIA EXECUTE E) 


B1E3 


A5D2 




LDA 




VTYPE 


; GET VAR TYPE 


B1E5 






RORfl 






• SHIFT DIM BIT TO CARRY 


B1E5 


+6A 




ROR 




A 




B1E6 


9003 " 


B1EB 


BCC 




:DC3 


- CONTINUE IF NOT YET DIM1 


B1E8 


202EB9 




:DCERR 


JSR 


ERRDIM 


■ ELSE ERROR 


B1EB 


38 




•DC3 


SEC 




• TURN ON 


B1EC 






ROLA 






■ DIM FLAG 


B1EC 


+2A 




ROL 




A 




B1ED 


85D2 




STA 




VTYPE 


- AND RESET 


B1EF 


302F " 


B220 


BMI 




:DCSTR 


• AND BR IF STRING 


B1F1 


A4F5 




LDY 




ZTEMP1 


; INC 11 BY 1 


B1F3 


A6F6 




LDX 




ZTEMP1+1 


; AND SET AS DIM1 


B1F5 


C8 




I NY 








B1F6 


D003 * 


B1FB 


BNE 




:DC4 




B1F8 


E8 




INX 








B1F9 


30ED " 


B1E8 


BMI 




: DCERR 


; BR IF OUT OF BOUNDS 


B1FB 


84D6 




:DC4 


STY 


VTYPE+EVAD1 




B1FD 


86D7 




STX 




VTYPE+EVAD1+1 




BIFF 


84F5 




STY 




ZTEMP1 


; ALSO PUT BACK ONTO 


B201 


86F6 




STX 




ZTEMP1+1 


; INDEX 1 FOR MULT 


B203 


A497 




LDY 




INDEX2 


- INC INDEX 2 BY 1 


B205 


A698 




LDX 




INDEX2+1 


; AND SET AS DIM 2 


B207 


C8 




INY 








B208 


D003 " 


B20D 


BNE 




:DC5 




B20A 


E8 




INX 








B20B 


30DB * 


B1E8 


BMI 




: DCERR 


; BR IF OUT OF BOUNDS 


B20D 


84D8 




:DC5 


STY 


VTYPE+EVAD2 




B20F 


86D9 




STX 




VTYPE+EVAD2+1 




B211 


205DAF 




JSR 




AMUL1 


: ZTEMP1 = ZTEMP1*D2 


B214 


2046AF 




JSR 




AMUL2 


; ZTEMP1 = ZTEMP1*6 

RESULT IS AN ARRAY 
SPACE REQD 


B217 


A4F5 




LDY 




ZTEMP1 


; A,Y = LENGTH 


B219 


A5F6 




LDA 




ZTEMP1+1 




B21B 


30CB * 


B1E8 


BMI 




: DCERR 




B21D 


4C34B2 




JMP 




: DCEXP 


; GO EXPAND 


B220 






:DCSTR 








B220 


A900 




LDA 




#0 


; SET CURRENT LENGTH =0 


B222 


85D6 




STA 




EVSLEN+VTYPE 




B224 


85D7 




STA 




EVSLEN+1+VTYPE 




B226 


A4F5 




LDY 




ZTEMP1 


; MOVE INDEX 


B228 


84D8 




STY 




VTYPE+EVSDIM 


; TO STR DIM 


B22A 


A5F6 




LDA 




ZTEMP1+1 


; [ALSO LOAD A,Y] 


B22C 


85D9 




STA 




VTYPE+EVSDIM+1 


,- FOR EXPAND 


B22E 


D004 * 


B234 


BNE 




: DCEXP 


,- INSURE DIM 


B230 


C000 




CPY 




#0 


; NOT ZERO 


B232 


F0B4 " 


B1E8 


BEQ 




: DCERR 


; FOR STRING 


B234 






:DCEXP 








B234 


A28E 




LDX 




#ENDSTAR 


,• POINT TO END ST 5, ARRAY 
SPACE 


B236 


2081A6 




JSR 




EXPAND 


I GO EXPAND 



210 



Source Code 



B239 


38 


B23A 


A597 


B23C 


E58C 


B23E 


85D4 


B240 


A598 


B242 


E58D 


B244 


85D5 


B246 


2016AC 


B249 


4CD9B1 



SEC 
LDA 
SBC 
STA 
LDA 
SBC 
STA 

JSR 
JMP 



SVESA 

STARP 

VTYPE+EVSADR 

SVESA+1 

STARP+1 

VTYPE+EVSADR+1 

RTNVAR 
:DC1 



CALCULATE DISPL INTO 

ST/ARRAY SPACE 

AND PUT INTO VALUE BOX 



RETURN TO VAR VALUE TABLE 
AND GO FOR NEXT ONE 



XPOKE — Execute POKE 



B24C 
B24C 
B24F 
B251 
B253 
B255 



20E0AB 

A5D4 

8595 

A5D5 

8596 



XPOKE 

JSR 
LDA 
STA 
LDA 
STA 



GETINT 

FR0 

POKADR 

FR0+1 

POKADR+1 



GET INTEGER ADDR 
SAVE POKE ADDR 



B257 20E9AB 



JSR 



GET 1 INT 



GET 1 BYTE INTEGER TO POKE 



B25A A5D4 LDA 

B25C A000 LDY 

B25E 9195 STA 

B260 60 RTS 

XDEG — Execute DEG 

B261 XDEG 

B261 A906 LDA 

B263 85FB STA 

B265 60 RTS 



FR0 

#0 

[POKADR], Y 



#DEGON 
RADFLG 



; GET INTEGER TO POKE 
; GET INDEX 
;GET INDEX 



GET DEGREES FLAG 

SET FOR TRANSCENDENTALS 



XRAD — Execute RAD 

B266 XRAD 

B266 A900 LDA 

B268 85FB STA 

B26A 60 RTS 



# RADON 
RADFLG 



XREST — Execute RESTORE Statement 



B26B 

B26B A900 

B26D 85B6 



XREST 

LDA 
STA 



#0 
DATAD 



GET RADIAN FLAG 

SET FOR TRANSCENDENTALS 



ZERO DATA DISPL 



B26F 
B272 
B274 
B275 



2010B9 

9003 "B277 

A8 

F007 "B27E 



B277 20D5AB 



B27A A5D5 
B27C A4D4 



JSR 
BCC 
TAY 
BEQ 



LDA 
LDY 



TSTEND 
:XR1 



FR0+1 
FR0 



TEST END OF STMT 
BR IF NOT END 
RESTORE TO LN=0 



GET LINE NO. 
LOAD LINE NO. 



B27E 85B8 
B280 84B7 
B282 60 



:XR2 STA DATALN+1 
STY DATALN 
RTS 



SET LINE 
DONE 



XREAD — Execute READ Statement 



B283 




XREAD 




B283 


A5A8 


LDA 


ST INDEX 


B285 


48 


PHA 




B286 


20C7B6 


JSR 


XGS 


B289 


A5B7 


LDA 


DATALN 


B28B 


85A0 


STA 


TSLNUM 


B28D 


A5B8 


LDA 


DATALN+1 


B28F 


85A1 


STA 


TSLNUM+1 



SAVE STINDEX 

SAVE READ STMT VIA GOSUB 

MOVE DATALN TO TSLNUM 



211 



Source Code 



B291 20A2A9 



B294 


A58A 


LDA 


B296 


85F3 


STA 


B298 


A58B 


LDA 


B29A 


85F4 


STA 


B29C 


2019B7 


JSR 


B29F 


68 


PLA 


B2A0 


85A8 


STA 


B2A2 




:XRD1 


B2A2 


A000 


LDY 


B2A4 


84F2 


STY 


B2A6 


2007B3 


JSR 


B2A9 


85B7 


STA 


B2AB 


2005B3 


JSR 


B2AE 


85B8 


STA 


B2B0 


2005B3 


JSR 


B2B3 


85F5 


STA 


B2B5 




:XRD2 


B2B5 


2005B3 


JSR 


B2B8 


85F6 


STA 


B2BA 


2005B3 


JSR 


B2BD 


C901 


CMP 


B2BF 


F026 ~B2E7 


BEQ 


B2C1 


A4F6 


LDY 


B2C3 


C4F5 


CPY 


B2C5 


B005 ~B2CC 


BCS 


B2C7 


88 


DEY 


B2C8 


84F2 


STY 


B2CA 


90E9 "B2B5 


BCC 



GETSTMT 

STMCUR 
INBUFF 
STMCUR+1 
INBUFF+1 

XRTN 

STINDEX 



#0 

CIX 

:XRNT1 

DATALN 

:XRNT 

DATALN+1 

:XRNT 

ZTEMP1 

:XRNT 

ZTEMP1+1 

:XRNT 

#CDATA 

:XRD4 

ZTEMP1+1 

ZTEMP1 

:XRD2A 

CIX 
:XRD2 



GO FIND TSLNUM 

MOVE STMCUR TO INBUFF 



RESTORE READ STMT VIA RETURN 
GET SAVED STINDEX 
SET IT 



SET CIX=0 

SET CIX 

GET LINE NO. LOW 

SET LINE NO. LOW 

SET LINE NO. HIGH 

SET LINE LENGTH 



SET STMT LENGTH 

GET STMT LINE TOKEN 
IS IT DATA 
BR IF DATA 

GET DISPL TO NEXT STMT 
IS IT EOL 
BR IF EOL 

SET NEW DISPL 

AND CONTINUE THIS STMT 



B2CC 84F2 

B2CE C6F2 

B2D0 A001 

B2D2 B1F3 

B2D4 303D "B313 



:XRD2A STY CIX 
DEC CIX 

:XRD3 LDY #1 

LDA [INBUFFLY 
BMI :XROOD 



WAS THIS STMT THE 

DIRECT ONE 

BR IF IT WAS [OUT OF DATA] 



B2D6 


38 




SEC 




B2D7 


A5F2 




LDA 


CIX 


B2D9 


65F3 




ADC 


INBUFF 


B2DB 


85F3 




STA 


INBUFF 


B2DD 


A900 




LDA 


#0 


B2DF 


85B6 




STA 


DATAD 


B2E1 


65F4 




ADC 


INBUFF+1 


B2E3 


85F4 




STA 


INBUFF+1 


B2E5 


90BB 


"B2A2 


BCC 


:XRD1 


B2E7 






:XRD4 




B2E7 


A900 




LDA 


*0 


B2E9 


85F5 




STA 


ZTEMP1 


B2EB 






:XRD5 




B2EB 


A5F5 




LDA 


ZTEMP1 


B2ED 


C5B6 




CMP 


DATAD 


B2EF 


B00B 


*B2FC 


BCS 


:XRD7 


B2F1 


2005B3 


:XRD6 JSR 


:XRNT 


B2F4 


D0FB 


~B2F1 


BNE 


:XRD6 


B2F6 


B0D8 


"B2D0 


BCS 


:XRD3 


B2F8 


E6F5 




INC 


ZTEMP1 


B2FA 


D0EF 


~B2EB 


BNE 


:XRD5 



INBUFF + CIX + 1 

= ADR NEXT PGM LINE 



GO SCAN THIS NEXT LINE 



I CLEAR ELEMENT COUNT 



GET ELEMENT COUNT 
AT PROPER ELEMENT 
BR IF AT 

ELSE SCAN FOR NEXT 
GET CHAR 

BR IF NOT CR OR COMMA 
BR IF CR 

INC ELEMENT COUNT 
AND GO NEXT 



B2FC A940 
B2FE 85A6 
B300 E6F2 



:XRD7 LDA #$40 
STA DIRFLG 
INC CIX 



SET READ BIT 

INC OVER DATA TOKEN 



212 



Source Code 



B302 4C35B3 



B305 




B305 


E6F2 


B307 


A4F2 : 


B309 


B1F3 


B30B 


C92C 


B30D 


18 


B30E 


F002 "B312 


B310 


C99B 


B312 


60 : 


B313 


2034B9 ': 



JMP 




:XINA 


XRNT 






INC 




CIX 


XRNT1 


LDY 


CIX 


LDA 




[INBUFF],Y 


CMP 




#52C 


CLC 






BEQ 




:XRNT2 


CMP 




#CR 


XRNT2 


RTS 




XROOD 


JSR 


ERROOD 



; GO DO IT 



INC INDEX 

GET INDEX 

GET CHAR COUNT 

IS IT A COMMA 

CARRY CLEAR FOR COMMA 

BR IF COMMA 

IS IT CR 



XINPUT — Execute INPUT 

B3I6 XINPUT 



B316 


A93F 


LDA 


#'?' 


B318 


85C2 


STA 


PROMPT 


B31A 


203EAB 


JSR 


GETTOK 


B31D 


C6A8 


DEC 


STINDEX 


B31F 


9005 "B326 


BCC 


:XIN0 


B321 


2002BD 


JSR 


GIOPRM 


B324 


85B4 


STA 


ENTDTD 


B326 




:XIN0 




B326 


2051DA 


JSR 


INTLBF 


B329 


2089BA 


JSR 


GLINE 


B32C 


204EB3 


JSR 


:XITB 


B32F 


A000 


LDY 


#0 


B331 


84A6 


STY 


DIRFLG 


B333 


84F2 


STY 


CIX 


B335 




:XINA 




B335 


203EAB 


JSR 


GETTOK 


B338 


E6A8 


INC 


STINDEX 


B33A 


A5D2 


LDA 


VTYPE 


B33C 


3020 ~B35E 


BMI 


:XISTR 


B33E 


2000D8 


JSR 


CVAFP 


B341 


B014 "B357 


BCS 


:XIERR 


B343 


2007B3 


JSR 


:XRNT1 


B346 


D00F "B357 


BNE 


.-XIERR 


B348 


2016AC 


JSR 


RTNVAR 


B34B 


4C89B3 


JMP 


:XINX 


B34E 


20F4A9 


:XITB JSR 


TSTBRK 


B351 


D001 "B354 


BNE 


XITBT 


B353 


60 


RTS 




B354 


4C93B7 


XITBT JMP 


XSTOP 


B357 


A900 


: XI ERR LDA 


*0 


B359 


85B4 


STA 


ENTDTD 


B35B 


2030B9 


JSR 


ERRINP 


B35E 




:XISTR 




B35E 


202EAB 


JSR 


EXPINT 


B361 


20BAAB 


JSR 


ARGPUSH 


B364 


C6F2 


DEC 


CIX 


B366 


A5F2 


LDA 


CIX 


B368 


85F5 


STA 


ZTEMP1 


B36A 


A2FF 


LDX 


#$FF 


B36C 


E8 


:XIS1 INX 




B36D 


2005B3 


JSR 


:XRNT 


B370 


D0FA "B36C 


BNE 


:XIS1 


B372 


B004 ~B378 


BCS 


:XIS2 


B374 


24A6 


BIT 


DIRFLG 


B376 


50F4 ~B36C 


BVC 


:XIS1 



SET PROMPT CHAR 

GET FIRST TOKEN 
BACK UP OVER IT 
BR IF NOT OPERATOR 
GO GET DEVICE NUM 
SET DEVICE NO. 



GO GET INPUT LINE 
TEST BREAK 

SET INPUT MODE 
SET CIX=0 

GO GET TOKEN 
INC OVER TOKEN 

IS A STR 

BR IF STRING 

CONVERT TO FP 

GET END TOKEN 

ERROR IF NO CR OR COMMA 

RETURN VAR 

GO FIGURE OUT WHAT TO DO 

NEXT 

GO TEST BREAK 

BR IF BRK 

DONE 

STOP 

RESET 

ENTER DVC 

GO ERROR 



INIT EXECUTE EXPR 

PUSH THE STRING 

DEC CIX TO CHAR 

BEFORE SOS 

SAVE THAT CIX 

SET CHAR COUNT = -1 

INC CHAR COUNT 

GET NEXT CHAR 

BR NOT CR OR COMMA 

BR IF CR 

IS IT COMMA, IF NOT READ 

THEN CONTINUE 



213 



Source Code 



B378 


A4P5 


:XIS2 


LDY 


ZTEMPI 


B37A 


A5A8 


LDA 




STINDEX 


B37C 


48 


PHA 






B37D 


8A 


TXA 






B37E 


A2F3 


LDX 




(tINBUFF 


B380 


2064AB 


JSR 




RISC 


B383 


68 


PLA 






B384 


85A8 


STA 




STINDEX 


B386 


20A6AE 


JSR 




RISASN 


B389 


24A6 


:XINX 


BIT 


DIRFLG 


B38B 


500F ~B39C 


BVC 




:XIN 


B38D 


E6B6 


INC 




DATAD 


B38F 


2010B9 


JSR 




TSTEND 


B392 


B00D "B3A1 


BCS 




:XIRTS 


B394 


2007B3 


:XIR1 


JSR 


:XRNT1 


B397 


9018 "B3B1 


BCC 




:XINC 


B399 


4CD0B2 


JMP 




:XRD3 


B39C 




:XIN 






B39C 


2010B9 


JSR 




TSTEND 


B39F 


9008 "B3A9 


BCC 




:XIN1 


B3A1 


2051DA 


:XIRTS 


JSR 


INTLBF 


B3A4 


A900 


LDA 




#0 


B3A6 


85B4 


STA 




ENTDTD 


B3A8 


60 


RTS 






B3A9 


2007B3 


:XIN1 


JSR 


:XRNT1 


B3AC 


9003 ~B3B1 


BCC 




:XINC 


B3AE 


4C26B3 


JMP 




:XIN0 



GET SAVED INDEX 
SAVE INDEX 

ACU = CHAR COUNT 
POINT TO INBUFF 
GO MAKE STR VAR 

RESTORE INDEX 
THEN DO STA ASSIGN 

IS THIS READ 
BR IF NOT 

INC DATA DISPL 
TEST END READ STMT 
BR IF READ END 

GET END DATA CHAR 

BR IF COMMA 

GO GET NEXT DATA LINE 



RESTORE LBUFF 
RESTORE ENTER 
DEVICE TO ZERO 
DONE 

IF NOT END OF DATA 
THEN BRANCH 
AND CONTINUE 



B3B1 E6F2 
B3B3 4C35B3 



:XINC INC CIX 
JMP :XINA 



INC INDEX 
AND CONTINUE 



XPRINT — Execute PRINT Statement 



B3B6 






B3B6 


A5C9 




B3B8 


85AF 




B3BA 


A900 




B3BC 


8594 




B3BE 


A4A8 




B3C0 


B18A 




B3C2 


C912 




B3C4 


F053 


"B419 


B3C6 


C916 




B3C8 


F07C 


"B446 


B3CA 


C914 




B3CC 


F078 


"B446 


B3CE 


C9I5 




B3D0 


F06F 


"B441 


B3D2 


C91C 




B3D4 


F061 


"B437 


B3D6 


20E0AA 


B3D9 


20F2AB 


B3DC 


C6A8 




B3DE 


24D2 




B3E0 


3016 


"B3F8 


B3E2 


20E6D8 


B3E5 


A900 




B3E7 


85F2 





XPRINT 
LDA 
STA 
LDA 

STA 



PTABW 
SCANT 

#0 
COX 



:XPR0 LDY STINDEX 
LDA [STMCUR],Y 



CMP 


#CCOM 


BEQ 


:XPTAB 


CMP 


#CCR 


BEQ 


:XPEOL 


CMP 


#CEOS 


BEQ 


:XPEOL 


CMP 


#CSC 


BEQ 


: XPNULL 


CMP 


JCPND 


BEQ 


:XPRIOD 


JSR 


EXEXPR 


JSR 


ARGPOP 


DEC 


STINDEX 


BIT 


VTYPE 


BMI 


:XPSTR 


JSR 


CVFASC 


LDA 


#0 


STA 


CIX 



GET TAB VALUE 

SCANT 

SET OUT INDEX 



GET STMT DISPL 
GET TOKEN 



BR IF TAB 
BR IF EOL 
BR IF EOL 
BR IF NULL 



GO EVALUATE EXPRESSION 

POP FINAL VALUE 

DEC STINDEX 

IS THIS A STRING 

BR IF STRING 

CONVERT TO ASCII 



B3E9 A4F2 



OUTPUT ASCII CHARACTERS 



214 



Source Code 



B3EB 
B3ED 
B3EE 
B3F0 
B3F3 
B3F4 
B3F6 
B3F8 
B3F8 
B3FB 
B3FD 
B3FF 
B401 
B403 
B405 
B407 

B409 
B40B 
B40D 
B40F 
B411 
B413 
B413 
B416 



B1F3 

48 

E6F2 

205DB4 

68 

10F3 "B3E9 

30C6 ~B3BE 

209BAB 

A900 

85F2 

A5D6 

D004 "B407 

C6D7 

30B7 "B3BE 

C6D6 

A4F2 

B1D4 

E6F2 

D002 ~B413 

E6D5 

205FB4 
4CFFB3 



LDA 
PHA 
INC 
JSR 
PLA 
BPL 
BMI 

XPSTR 
JSR 
LDA 
STA 

XPR2C 
BNE 
DEC 
BMI 

XPR2B 

XPR2 

LDA 
INC 
BNE 
INC 
:XPR2A 
JSR 
JMP 



[INBUFF], Y 

CIX 
:XPRC 

:XPR1 
:XPR0 

GSTRAD 

#0 

CIX 

VTYPE+EVSLEN 
:XPR2B 

VTYPE+EVSLEN+1 
:XPR0 

VTYPE+EVSLEN 

CIX i 

[VTYPE+EVSADR],Y 
CIX ; 

:XPR2A 
VTYPE+EVSADR+1 

:XPRC1 
:XPR2C 



FROM INBUFF 
UNTIL THE CHAR 
WITH THE MSB ON 
IS FOUND 



THEN GO FOR NEXT TOKEN 
GO GET ABS STRING ARRAY 



; IF LEN LOW 
NOT ZERO BR 
DEC LEN HI 
BR IF DONE 

; DEC LEN LOW 

OUTPUT STRING CHARS 
; FOR THE LENGTH 
OF THE STRING 



~ 



B419 
B419 
B41B 
B41C 
B41E 
B420 
B421 
B423 
B42 5 
B427 

B429 
B42B 
B42D 
B42F 
B431 
B434 

B437 
B43A 
B43C 
B43E 

B441 
B441 
B443 

B446 
B446 
B448 
B449 
B44B 
B44D 
B44F 
B451 
B453 
B455 
B458 
B458 
B45A 
B45C 



A494 

C8 

C4AF 

9009 

18 

A5C9 

65AF 

85AF 

90F0 



B419 



A494 

C4AF 

B012 "B441 

A920 

205DB4 

4C29B4 

2002BD 
85B5 
C6A8 
4CBEB3 



E6A8 
4CBEB3 



A4A8 

88 

B18A 

C915 

F009 "E 

C912 

F005 ~E 

A99B 

205FB4 



A900 
85B5 
60 



:XPTAB 
:XPR3 LDY 

I NY 

CPY 

BCC 
:XPIC3 CLC 

LDA 

ADC 

STA 

BCC 



SCANT 
:XPR4 

PTABW 
SCANT 
SCANT 
:XPR3 



: XPR4 LDY COX 
CPY SCANT 
BCS :XPR4A 
LDA #$20 
JSR :XPRC 
JMP :XPR4 

:XPRIOD JSR GIOPRM 

STA LISTDTD 

DEC STINDEX 

JMP :XPR0 



B45D 297F 
B45F E694 



XPR4A 






XPNULL 


INC 


STINDEX 


JMP 




:XPR0 


XPEOL 






XPEOS 


LDY 


STINDEX 


DEY 






LDA 




[STMCUR],Y 


CMP 




#CSC 


BEQ 




: XPRTN 


CMP 




#CCOM 


BEQ 




: XPRTN 


LDA 




#CR 


JSR 




:XPRC1 


XPRTN 






LDA 




#0 


STA 




LISTDTD 


RTS 






XPRC 


AND 


#?7F 


XPRC1 


INC 


COX 



DO UNTIL COX+1 < SCANT 



SCANT = SCANT+TAB 



DO UNTIL COX = SCANT 



PRINT BLANKS 



GET DEVICE NO. 
SET AS LIT DEVICE 
DEC INDEX 
GET NEXT TOKEN 



INC STINDEX 



AT END OF PRINT 

IF PREV CHAR WAS 
SEMI COLON THEN DONE 
ELSE PRINT A CR 
OR A COMMA 
THEN DONE 

THEN DONE 

SET PRIMARY 
LIST DVC = 

AND RETURN 



MSB OFF 

INC OUT INDEX 



215 



Source Code 



B461 4C9FBA 



OUTPUT CHAR 



XLPRINT- Print to Printer 



B464 




XLPRINT 






B464 


A980 


LDA 


SPSTRS.255 


POINT TO FILE SPEC 


B466 


85F3 


STA 


INBUFF 


X 


B468 


A9B4 


LDA 


#PSTR/256 


X 


B46A 


B5F4 


STA 


INBUFF+1 


X 


B46C 


A207 


LDX 


#7 


GET DEVICE 


B46E 


86B5 


STX 


LISTDTD 


SET LIST DEVICE 


B470 


A900 


LDA 


#0 


GET AUX 2 


B47 2 


A008 


LDY 


#8 


GET OPEN TYPE 


B474 


20D1BB 


JSR 


SOPEN 


DO OPEN 


B477 


20B3BC 


JSR 


IOTEST 


TEST FOR ERROR 


B47A 


20B6B3 


JSR 


XPRINT 


DO THE PRINT 


B47D 


4CF1BC 


JMP 


CLSYS1 


CLOSE DEVICE 



B480 


50 


PSTR DB 


ipi 




B481 


3A9B 


DB 


' : ' ,CR 




XLIST 


— Execute LIST Command 






B483 




XLIST 






B483 


A000 


LDY 


#0 


SET TABLE SEARCH LINE NO 


B485 


84A0 


STY 


TSLNUM 


TO ZERO 


B487 


84A1 


STY 


TSLNUM+1 




B489 


88 


DEY 






B48A 


84AD 


STY 


LELNUM 


SET LIST END LINE NO 


B48C 


A97F 


LDA 


#57F 


TO $7FFF 


B48E 


85AE 


STA 


LELNUM+1 




B490 


8DFE02 


STA 


$2FE 


SET NON-DISPLAY MODE 


B493 


A99B 


LDA 


#CR 


POINT CR 


B495 


209FBA 


JSR 


PRCHAR 




B498 


20C7B6 


JSR 


XGS 


SAVE CURLINE VIA GOSUB 


B49B 




:XL0 






B49B 


A4A8 


LDY 


STINDEX 


GET STMT INDEX 


B49D 


C8 


I NY 




INC TO NEXT CHAR 


B49E 


C4A7 


CPY 


NXTSTD 


RT NEXT STMT 


B4A0 


B02D "B4CF 


BCS 


:LSTART 


BR IF AT, NO PARMS 


B4A2 


A5A8 


LDA 


STINDEX 


SAVE STINDEX 


B4A4 


48 


PHA 




ON STACK 


B4A5 


200FAC 


JSR 


POP1 


POP FIRST ARGUMENT 


B4A8 


68 


PLA 




RESTORE STINDEX TO 


B4A9 


85A8 


STA 


STINDEX 


RE-DO FIRST ARG 


B4AB 


A5D2 


LDA 


VTYPE 


GET VAR TYPE 


B4AD 


1006 "B4B5 


BPL 


:XL1 


BR IF NOT FILE SPEC STRING 


B4AF 


20D5BA 


JSR 


FLIST 


GO OPEN FILE 


B4B2 


4C9BB4 


JMP 


:XL0 


GO BACK TO AS IF FIRST PARM 


B4B5 




:XL1 






B4B5 


20D5AB 


JSR 


GETPINT 


GO GET START LNO 


B4B8 


85A1 


STA 


TSLNUM+1 




B4BA 


A5D4 


LDA 


FR0 


MOVE START LNO 


B4BC 


85A0 


STA 


TSLNUM 


TO TSLNUM 


B4BE 


A4A8 


LDY 


STINDEX 


GET STMT INDEX 


B4C0 


C4A7 


CPY 


NXTSTD 


AT NEXT STMT 


B4C2 


F003 "B4C7 


BEQ 


:LSE 


BR IF AT, NO PARMS 



216 



Source Code 



B4C4 20D5AB 



GO GET LINE NO 



B4C7 


A5D4 




:LSE 


LDA 


FR0 


B4C9 


85AD 




STA 




LELNUM 


B4CB 


A5D5 




LDA 




FR0+1 ; 


B4CD 


85AE 




STA 




LELNUM+1 


B4CF 






: LSTART 






B4CF 


20A2A9 




JSR 




GETSTMT 


B4D2 


20E2A9 




:LNXT 


JSR 


TENDST ; 


B4D5 


3024 * 


B4FB 


BMI 




: LRTN I 


B4D7 


A001 




:LTERNG 


LDY 


#1 


B4D9 


B18A 




LDA 




[STMCUR],Y ; 


B4DB 


C5AE 




CMP 




LELNUM+1 ; 


B4DD 


900B " 


B4EA 


BCC 




:LGO 


B4DF 


D01A * 


B4FB 


BNE 




: LRTN 


B4E1 


88 




DEY 






B4E2 


B18A 




LDA 




[STMCUR],Y 


B4E4 


C5AD 




CMP 




LELNUM 


B4E6 


9002 * 


B4EA 


BCC 




:LGO 


B4E8 


D011 " 


B4FB 


BNE 




:LRTN 


B4EA 


205CB5 




:LGO 


JSR 


:LLINE ; 


B4ED 


20F4A9 




JSR 




TSTBRK ; 


B4F0 


D009 * 


B4FB 


BNE 




: LRTN ; 


B4F2 


20DDA9 




JSR 




GETLL 


B4F5 


20D0A9 




JSR 




GNXTL ; 


B4F8 


4CD2B4 




JMP 




:LNXT ; 


B4FB 






:LRTN 






B4FB 


A5B5 




LDA 




LISTDTD ; 


B4FD 


F007 " 


3506 


BEQ 




: LRTN1 ; 


B4FF 


20F1BC 




JSR 




CLSYSD ; 


B502 


A900 




LDA 




#0 


B504 


85B5 




STA 




LISTDTD 


B506 






:LRTN1 






B506 


8DFE02 




STA 




S2FE ; 


B509 


4C19B7 




JMP 




XRTN ; 



MOVE END LINE NO 
TO LIST END LINE NO 



GO FIND FIRST LINE 

AT END OF STMTS 
BR AT END 

COMPARE CURRENT STMT 
LINE NO WITH END 
LINE NO 



GO LIST THE LINE 
TEST FOR BREAK 
BR IF BREAK 

GO INC TO NEXT LINE 
GO DO THIS LINE 



IF LIST DEVICE 
IS ZERO, BR 
ELSE CLOSE DEVICE 
AND RESET 
DEVICE TO ZERO 

SET DISPLAY MODE 

THEN RESTORE LIST LINE 

AND RETURN 



LSCAN — Scan a Table for LIST Token 



B50C 

B50C 86AA 

B50E 2030B5 

B511 A4AA 

B513 C6AF 

B515 300E 



'B525 



LSCAN 
STX 
JSR 

LSC0 

DEC 
BMI 



ENTRY PARMS 

X = SKIP LENGTH 
A,Y = TABLE ADR 
SCANT = TOKEN 



SRCSKP 
:LSST 



SCANT 
:LSINC 



SAVE SKIP LENGTH 
SAVE SRC ADR 



GET SKIP FACTOR 



DECREMENT SRC COUNT 
BR IF DONE 



B517 
B5I9 
B51B 
B51C 
B51E 
B51F 
B522 



B195 

3003 "B51E 

C8 

D0F9 "B517 

C8 

2025B5 

4C11B5 



:LSC1 LDA 

BMI 

INY 

BNE 
:LSC2 INY 

JSR 

JMP 



CSRCADR], Y 
:LSC2 



:LSINC 
:LSC0 



; GET CHARACTER 
BR IF LAST CHARACTER 
INC TO NEXT 
BR ALWAYS 

INC TO AFTER LAST CHAR 
INC SRC ADR BY Y 
GO TRY NEXT 



B525 18 

B526 98 

B527 6595 

B529 8595 



:LSINC CLC 
TYA 

ADC SRCADR 
STA SRCADR 



Y PLUS 
SRCADR 
IS 






217 



Source Code 



B52B 


A8 


TAY 






B52C 


A596 


LDA 




SRCADR+1 ; 


B52E 


6900 


ADC 




#0 


B530 


8596 


': LSST 


STA 


SRCADR+1 ; 


B532 


8495 


STY 




SRC ADR 


B534 


60 


RTS 






LPRTOKEN — Print 


a Token 






B535 




LPRTOKEN 






B535 




: LPRTOKEN 




B535 


A0FF 


LDY 




#?FF 


B537 


84AF 


STY 




SCANT 


B539 


E6AF 


:LPT1 


INC 


SCANT ; 


B53B 


A4AF 


LDY 




SCANT ; 


B53D 


B195 


LDA 




[SRCADR],Y ,- 


B53F 


48 


PHA 






B540 


C99B 


CMP 




#cr ; 


B542 


F004 "B548 


BEQ 




:LPT1A J 


B544 


297F 


AND 




#$7F ; 


B546 


F003 "B54B 


BEQ 




:LPT2 ; 


B548 




:LPT1A 






B548 


209FBA 


JSR 




PRCHAR ,- 


B54B 




:LPT2 






B54B 


68 


PLA 






B54C 


10EB "B539 


BPL 




: LPT1 


B54E 


60 


RTS 






LPTWB — Print Token with Bla 


nk Before and After 


B54F 




: LPTWB 






B54F 


A920 


LDA 




#$20 


B551 


209FBA 


JSR 




PRCHAR 


B554 


2035B5 


: LPTTB 


JSR 


: LPRTOKEN 


B557 


A920 


:LPBLNK 


LDA 


#?20 


B559 


4C9FBA 


JMP 




PRCHAR 



NEW 
SRCADR 



STORE NEW SRCADR 

AND 

RETURN 



INITIALIZE INDEX TO ZERO 



INC INDEX 

GET INDEX 

GET TOKEN CHAR 

SAVE CHAR 

IF ATARI CR 

THEN DON'T AND 

TURN OFF MSB 

BR IF NON-PRINTING 

GO PRINT CHAR 

GET CHAR 

BR IF NOT END CHAR 

GO BACK TO MY BOSS 



GET BLANK 

GO PRINT IT 

GO PRINT TOKEN 

GET BLANK 

GO PRINT IT AND RETURN 



LLINE — List a Line 



B55C 




LLINE 










B55C 




: LLINE 










B55C 


A000 


LDY 


#0 








B55E 


B18A 


LDA 


[STMCUR] 


Y 


MOVE LINE NO 


B560 


85D4 


STA 


FR0 




TO FR0 


B562 


C8 


I NY 










B563 


B18A 


LDA 


[STMCUR] 


Y 






B565 


85D5 


STA 


FR0+1 








B567 


20AAD9 


JSR 


CVIFP 




CONVERT TO FP 


B56A 


20E6D8 


JSR 


CVFASC 




CONVERT TO ASCII 


B56D 


A5F3 


LDA 


INBUFF 




MOVE INBUFF ADR 


B56F 


8595 


STA 


SRCADR 




TO SRCADR 


B571 


A5F4 


LDA 


INBUFF+I 








B573 


8596 


STA 


SRCADR+1 








B575 


2054B5 


JSR 


: LPTTB 




AND 


PRINT LINE NO 


B578 




LDLINE 










B578 


A002 


LDY 


#2 








B57A 


B18A 


LDA 


[STMCUR] 


Y 


GET 


LINE LENGTH 


B57C 


859F 


STA 


LLNGTH 




AND 


SAVE 


B57E 


C8 


I NY 










B57F 


B18A 


:LL1 LDA 


[STMCUR], Y 


j 


C-ET STMT LENGTH 


B581 


85A7 


STA 


NXTSTD 




AND 


SAVE AS NEXT ST DISPL 


B583 


C8 


INY 






INC 


TO STMT TYPE 


B584 


84A8 


STY 


STINDEX 




AND 


SAVE DISPL 


B586 


2090B5 


JSR 


:LSTMT 




GO LIST STMT 



218 



Source Code 



B589 


A4A7 




LDY 


NXTSTD 


B58B 


C49F 




CPY 


LLNGTH 


B58D 


90F0 


"B57F 


BCC 


:LL1 


B58F 


60 




RTS 





DONE LINE 



BR IF NOT 
ELSE RETURN 



LSTMT — List a Statement 



B590 




: LSTMT 




B590 


203IB6 


JSR 


:LGCT 


B593 


C936 


CMP 


#CILET 


B595 


F017 "B5AE 


BEQ 


:LADV 


B597 


203DB6 


JSR 


LSTMC 


B59A 


2031B6 


JSR 


:LGCT 


B59D 


C937 


CMP 


#CERR 


B59F 


F004 "B5A5 


BEQ 


:LDR 


B5A1 


C902 


CMP 


#2 


B5A3 


B009 ~B5AE 


BCS 


:LADV 


B5A5 


202FB6 


:LDR JSR 


:LGNT 


B5A8 


209FBA 


JSR 


PRCHAR 


B5AB 


4CA5B5 


JMP 


:LDR 


B5AE 


202FB6 


: LADV JSR 


:LGNT 


B5BI 


101A ~B5CD 


BPL 


:LNVAR 


B5B3 


297F 


AND 


#$7F 


B5B5 


85AF 


STA 


SCANT 


B5B7 


A200 


LDX 


#0 


B5B9 


A583 


LDA 


VNTP+1 


B5BB 


A482 


LDY 


VNTP 


B5BD 


200CB5 


JSR 


:LSCAN 


B5C0 


2035B5 


:LS1 JSR 


:LPRTOKEN 


B5C3 


C9A8 


CMP 


#$A8 


B5C5 


D0E7 "B5AE 


BNE 


:LADV 


B5C7 


202FB6 


JSR 


:LGNT 


B5CA 


4CAEB5 


JMP 


:LADV 


B5CD 




:LNVAR 




B5CD 


C90F 


CMP 


#$0F 


B5CF 


F018 "B5E9 


BEQ 


:LSTC 



B5D1 B036 "B609 



B5D3 


204DAB 


JSR 




NCTOFR0 


B5D6 


C6A8 


DEC 




STINDEX 


B5D8 


20E6D8 


JSR 




CVFASC 


B5DB 


A5F3 


LDA 




INBUFF 


B5DD 


8595 


STA 




SRCADR 


B5DF 


A5F4 


LDA 




INBUFF+1 


B5E1 


8596 


STA 




SRCADR+1 


B5E3 


2035B5 


:LSX 


JSR 


rLPRTOKEN 


B5E6 


4CAEB5 


JMP 




:LADV 


B5E9 


202FB6 


:LSTC 


JSR 


:LGNT 


B5EC 


85AF 


STA 




SCANT 


B5EE 


A922 


LDA 




#$22 


B5F0 


209FBA 


JSR 




PRCHAR 


B5F3 


A5AF 


LDA 




SCANT 


B5F5 


F00A "B601 


BEQ 




:LS3 



GET CURRENT TOKEN 

IF IMP LET 

BR 

GO LIST STMT CODE 

GO GET CURRENT TOKEN 
BR IF ERROR STMT 

WAS IT DATA OR REM 
BR IF NOT 

OUTPUT DATA/REM 
THEN PRINT THE CR 



GET NEXT TOKEN 

BR IF NOT VARIABLE 

TURN OFF MSB 

AND SET AS SCAN COUNT 

SCAN VNT FOR 

VAR NAME 



PRINT VAR NAME 

NAME END IN LPAREN 

BR IF NOT 

DON'T PRINT NEXT TOKEN 

IF IT IS A PAREN 



TOKEN: ?0F 

BR IF 0F, STR CONST 

BR IF TOKEN >$0F 

ELSE IT'S NUM CONST 
GO MOVE FR0 

BACK INDEX TO LAST CHAR 
CONVERT FR0 TO ASCII 
POINT SCRADR 
TO INBUFF WHERE 
CHAR IS 

GO PRINT NUMBER 
GO FOR NEXT TOKEN 

GET NEXT TOKEN 
WHICH IS STR LENGTH 
PRINT DOUBLE QUOTE CHAR 



B5F7 202FB6 

B5FA 209FBA 

B5FD C6AF 

B5FF D0F6 "B5F7 



:LS2 JSR :LGNT 

JSR PRCHAR 

DEC SCANT 

BNE :LS2 



OUTPUT STR CONST 
CHAR BY CHAR 
UNTIL COUNT =0 



B601 

B601 A922 

B603 209FBA 

B606 4CAEB5 



:LS3 



LDA 
JSR 
JMP 



#$22 

PRCHAR 

:LADV 



THEN OUTPUT CLOSING 
DOUBLE QUOTE 



219 



Source Code 



B609 


38 


:LOP SEC 




B60A 


E910 


SBC 


#510 


B60C 


85AF 


STA 


SCANT 


B60E 


A200 


LDX 


#0 


B610 


A9A7 


LDA 


#OPNTAB/256 


B612 


A0E3 


LDY 


#OPNTAB&255 


B614 


200CBS 


JSR 


:LSCAN 


B617 


2031B6 


JSR 


:LGCT 


B61A 


C93D 


CMP 


#CFFUN 


B61C 


B0C5 "B5E3 


BCS 


:LSX 


B61E 


A000 


LDY 


#0 


B620 


B195 


LDA 


[SRCADRJ.Y 


B622 


297F 


AND 


#$7F 


B624 


20F7A3 


JSR 


TSTALPH 


B627 


B0BA "B5E3 


BCS 


:LSX 


B629 


204FB5 


JSR 


:LPTWB 


B62C 


4CAEB5 


JMP 


:LADV 


B62F 




:LGNT 




B62F 


E6A8 


INC 


STINDEX 


B631 


A4A8 


: LGCT LDY 


STINDEX 


B633 


C4A7 


CPY 


NXTSTD 


B635 


B003 "B63A 


BCS 


: LGNTE 


B637 


B18A 


LDA 


[STMCUR],Y 


B639 


60 


RTS 




B63A 


60 


: LGNTE PLA 




B63B 


68 


PLA 




B63C 


60 


RTS 




B63D 




LSTMC 




B63D 


85AF 


STA 


SCANT 


B63F 


A202 


LDX 


#2 


B641 


A9A4 


LDA 


fSNTAB/256 


B643 


A0AF 


LDY 


#SNTAB&255 


B645 


200CB5 


JSR 


:LSCAN 


B648 


4C54B5 


JMP 


: LPTTB 



SUBSTRACT THE 10 
SET FOR SCAN COUNT 



SCAN OP NAME TABLE 
GO GET CURRENT TOKEN 
IS IT FUNCTION 
BR IF FUNCTION 

GET FIRST CHAR 
TURN OFF MSB 
TEST FOR ALPHA 
BR NOT ALPHA 
LIST ALPHA WITH 
BLANKS FOR AND AFTER 

GET NEXT TOKEN 
INC TO NEXT 
GET DISPL 
AT END OF STMT 
BR IF AT END 
GET TOKEN 
AND RETURN 

POP CALLERS ADR 

AND 

GO BACK TO LIST LINE 



SET INSCAN COUNT 
AND 



STATEMENT NAME TABLE 

GO LIST WITH FOLLOWING BLANK 



XFOR — Execute FOR 



B64B 




B64B 




B64B 


208AB8 


B64E 


20E0AA 


B651 


A5D3 


B653 


0980 


B655 


48 


B656 


2025B8 



JSR 


: SAVDEX 


JSR 


EXEXPR 


LDA 


VNUM 


ORA 


#$80 


PHA 




JSR 


FIXRSTK 



SAVE STINDEX 

DO ASSIGNMENT 

GET VARIABLE # 

OR IN HIGH ORDER BIT 

SAVE ON CPU STACK 

FIX RUN STACK 



BUILD STACK ELEMENT 



B659 


A90C 




LDA 




#FBODY 


B65B 


2078B8 




JSR 




: REXPAN 


B65E 


200FAC 




JSR 




POP1 






; 

! 




PUT 


LIMIT [ 


B661 


A2D4 




LDX 




#FR0 


B663 


A000 




LDY 




#FLIM 


B665 


208FB8 




JSR 




:MV6RS 



; GET # OF BYTES 
; EXPAND RUN STACK 



; EVAL EXP & GET INTO FR0 



POINT TO FR0 
GET DISPL 
GO MOVE LIMIT 



SET DEFAULT STEP 



B668 2044DA 

B66B A901 

B66D 85D5 

B66F A940 

B671 85D4 



JSR 


ZFR0 


LDA 


#1 


STA 


FR0 + 1 


LDA 


#$40 


STA 


FR0 



CLEAR FR0 TO ZEROS 

GET DEFAULT STEP 

SET DEFAULT STEP VALUE 

GET DEFAULT EXPONENT 

STORE 



220 



Source Code 



TEST FOR END OF STMT 



B673 2010B9 
B676 B003 "B67B 



B678 200FAC 
B67B 



B67B A2D4 
B67D A006 
B67F 208FB8 



JSR 
BCS 



TSTEND 
:NSTEP 



JSR 

:NSTEP 



ELSE GET STEP VALUE 
POP1 



TEST FOR END OF START 
IF YES, WE ARE AT END OF 
STMT 



EVAL EXP & GET INTO FR0 



PUT STEP [IN FR0] ON STACK 



LDX 


#FR0 


LDY 


#FSTEP 


JSR 


:MV6RS 



POINT TO FR0 
GET DISPL 
GO MOVE STEP 



B682 68 



B683 




'SHRSTK 


EXPAND RUN STACK 


B683 


48 


PHA 




B684 


A904 


LDA 


#GFHEAD ; 


B686 


2078B8 


JSR 


: REXPAN ; 
PUT ELEMENT ON STACK 


B689 


68 


PLA 




B68A 


A000 


LDY 


#GFTYPE ; 


B68C 


91C4 


STA 


[TEMPA],Y ; 


B68E 


B18A 


LDA 


[STMCUR],Y 


B690 


C8 


INY 




B691 


91C4 


STA 


[TEMPA],Y 


B693 


B18A 


LDA 


[STMCUR],Y ; 


B695 


C8 


INY 




B696 


91C4 


STA 


[TEMPA],Y ; 


B698 


A6B3 


LDX 


SAVDEX ; 


B69A 


CA 


DEX 




B69B 


8A 


TXA 




B69C 


C8 


INY 




B69D 


91C4 


STA 


[TEMPA],Y ; 


B69F 


60 


RTS 





; GET VARIABLE # 

PSHRSTK - PUSH COMMON PORT OF FOR/GOSUB 
- ELEMENT ON RUN STACK 

ON ENTRY A - VARIABLE # OR [FOR GOSUB] 
TSLNUM - LINE # 
STINDEX - DISPL TO STMT TOKEN +1 



SAVE VAR # / TYPE 

GET # OF BYTES TO EXPAND 

EXPAND [OLD TOP RETURN IN 

ZTEMP1] 



GET VARIABLE #/TYPE 

GET DISPL TO TYPE IN HEADER 

PUT VAR#/TYPE ON STACK 

GET LINE # LOW 
POINT TO NEXT HEADER BYTE 
PUT LINE # LOW IN HEADER 
GET LINE # HIGH 

PUT IN HEADER 

GET SAVED INDEX INTO LINE 
POINT TO TOKEN IN LINE 
PUT IN A 

POINT TO DISPL IN HEADER 
PUT IN HEADER 



XGOSUB — Execute GOSUB 



B6A0 

B6A0 20C7B6 



XGOSUB 
JSR 



GO TO XGS ROUTINE 



XGOTO — Execute GOTO 

B6A3 XGOTO 

B6A3 20D5AB JSR 



B6A6 

B6A6 A5D5 

B6A8 85A1 

B6AA A5D4 

B6AC 85A0 



GETPINT ; GET POSTIVE INTEGER IN FR0 

GET LINE ADRS & POINTERS 



X 
X 

PUT LINE # IN TSLNUM 
X 



LDA 


FR0 + 1 


STA 


TSLNUM+1 


LDA 


FR0 


STA 


TSLNUM 



221 



Source Code 



B6AE 




XG01 




B6AE 


20A2A9 


JSR 


GETSTMT 


B6B1 


B005 "B6B8 


BCS 


:ERLN 


B6B3 


68 


PLA 




B6B4 


68 


PLA 




B6B5 


4C5FA9 


JMP 


EXECNL 


B6B8 




:ERLN 




B6B8 


20BEB6 


JSR 


RESCUR 



; LINE POINTERS AND STMT ADDRESS 
; IF NOT FOUND ERROR 
; CLEAN UP STACK 

; GO TO EXECUTE CONTROL 



RESTORE STMT CURRENT 



B6BB 2028B 

B6BE 

B6BE A5BE 

B6C0 858A 

B6C2 A5BF 

B6C4 858B 

B6C6 60 



XGS — Perform GOSUB [GOSUB, LIST, READ] 

XGS 



JSR 


ERNOLN 


RESCUR 




LDA 


SAVCUR 


STA 


STMCUR 


LDA 


SAVCUR+1 


STA 


STMCUR+1 


RTS 





208AB8 



B6C7 

B6C7 

B6CA 

B6CA A900 

B6CC 4C83B6 



XGS I 



JSR 


: SAVDEX 


LDA 


#0 


JMP 


PSHRSTK 



LINE # NOT FOUND 

RESTORE STMCUR 

X 

X 

X 



GET STMT INDEX 



GET GOSUB TYPE 

PUT ELEMENT ON RUN STACK 



XNEXT— Execute NEXT 

B6CF XNEXT 



B6CF A4A8 
B6D1 B18A 
B6D3 85C7 



B6D5 

B6D5 2041B8 

B6D8 B03C "B716 

B6DA F03A ~B716 

B6DC C5C7 

B6DE D0F5 "B6D5 



LDY 
LDA 
STA 



GET VARIABLE # 

STINDEX 

[ STMCUR ],Y 

ZTEMP2+1 

GET ELEMENT 



BCS 
BEQ 
CMP 
BNE 



:ERNFOR 
:ERNFOR 
ZTEMP2+1 
:XN 



GET STMT INDEX 
GET VARIABLE f 
SAVE 



PULL ELEMENT FROM RUN STACK 

VAR#/TYPE RETURN IN A 
IF AT TOP OF STACK, ERROR 
IF TYPE = GOSUB, ERROR 
DOES STKVAR* = OUR VAR # 



GET STEP VALUES IN FR1 



B6E0 A006 
B6E2 209EB8 



B6E5 A5E0 
B6E7 48 



LDY 
JSR 



#FSTEP 
:PL6RS 



GET DISPL INTO ELEMENT 
GET STEP INTO FR1 



SAVE TYPE OF STEP [+ OR -] 



LDA 
PHA 



GET EXP FR1 [CONTAINS SIGN] 
PUSH ON CPU STACK 



B6E8 A5C7 
B6EA 2089AB 



B6ED 203BAD 
B6F0 2016AC 



GET VARIABLE VALUE 



LDA 
JSR 



ZTEMP2+1 
GETVAR 



GET NEW VALUE 



JSR 
JSR 



FRADD 
RTNVAR 



GET LIMIT IN FR1 



,- GET VAR # 

; GET VARIABLE VALUE 



ADD STEP TO VALUE 
PUT IN VARIABLE TABLE 



222 



Source Code 



B6F3 


A000 


LDY 


B6F5 


209EB8 


JSR 


B6F8 


68 


PLA 


B6F9 


1006 "B701 


BPL 


B6FB 


2035AD 


JSR 


B6FE 


1009 ~B709 


BPL 


B700 


60 


RTS 



#FLIM 
:PL6RS 



GET DISPL TO LIMIT IN ELEMENT 
GET LIMIT INTO FR1 
GET SIGN OF STEP 
BR IF STEP + 



COMPARE FOR NEGATIVE STEP 



FRCMP 
:NEXT 



COMPARE VALUE TO LIMIT 

IF VALUE >= LIMIT, CONTINUE 

ELSE DONE 



COMPARE FOR POSTIVE STEP 



B701 




:STPPL 




B701 


2035AD 


JSR 


FRCMP ; 


B704 


F003 "B709 


BEQ 


:NEXT ; 


B706 


3001 "B709 


BMI 


: NEXT ; 


B708 


60 


RTS 




B709 




•NEXT 




B709 


A910 


LDA 


#GFHEAD+FBODY 


B70B 


2078B8 


JSR 


: REXPAND ; 


B70E 


2037B7 


JSR 


:GETTOK ; 


B711 


C908 


CMP 


#CFOR ; 


B713 


D032 "B747 


BNE 


:ERGFD ; 


B715 


60 


RTS 




B716 




:ERNFOR 




B716 


2026B9 


JSR 


ERNOFOR 



COMPARE VALUE TO LIMIT 
IF = CONTINUE 
IF < CONTINUE 
ELSE RETURN 



GET # BYTES IN FOR ELEMENT 
GO PUT IT BACK ON STACK 
GET TOKEN [RETURNS IN A] 
IS TOKEN = FOR? 
IF NOT IT'S AN ERROR 



XRTN — Execute RETURN 



B719 






XRTN 




B719 


2041B8 


JSR 


POPRSTK ; 


B71C 


B016 


"B734 


BCS 


:ERRTN ; 


B71E 


DBF 9 


"B719 


BNE 


XRTN 


B720 


2037B7 


JSR 


:GETTOK ; 


B723 


C90C 




CMP 


#CGOSUB ; 


B725 


F00C 


"B733 


BEQ 


: XRTS ; 


B727 


C91E 




CMP 


#CON 


B729 


F008 


"B733 


BEQ 


:XRTS j 


B72B 


C904 




CMP 


#CLIST 


B72D 


F004 


"B733 


BEQ 


:XRTS ; 


B72F 


C922 




CMP 


#CREAD ; 


B731 


D014 


~B747 


BNE 


:ERGFD ,- 


B733 






:XRTS 




B733 


60 




RTS 




B734 






:ERRTN 




B734 


2020B9 


JSR 


ERBRTN ; 



GET ELEMENT FROM RUN STACK 
IF AT TOP OF STACK, ERROR 
IF TYPE NOT GOSUB, REPEAT 

GET TOKEN FROM LINE [IN A] 
IS IT GOSUB? 
BR IF GOSUB 

BR IF ON 

BR IF LIST 
MAYBE IT'S READ 
IF NOT, ERROR 



BAD RETURN ERROR 



:GETTOK - GET TOKEN POINTED TO BY RUN STACK ELEMENT 
ON EXIT A - CONTAINS TOKEN 



B737 




:GETTOK 




B737 


2018B8 


JSR 


SETLINE ; 


B73A 


B00B ~B747 


BCS 


:ERGFD 


B73C 


A4B2 


LDY 


SVDISP j 


B73E 


88 


DEY 




B73F 


B18A 


LDA 


[STMCUR],Y ; 


B741 


85A7 


STA 


NXTSTD ; 


B743 


C8 


I NY 




B744 


B18A 


LDA 


[STMCUR],Y ; 


B746 
B747 


60 


RTS 
:ERGFD 





SET UP TO PROCESS LINE 

IF LINE # NOT FOUND, ERROR 

GET DISPL TO TOKEN 
POINT TO NXT STMT DISPL 
GET NEXT STMT DISPL 
SAVE 



GET DISPL TO TOKEN AGAIN 
GET TOKEN 



223 



Source Code 



B747 


20BEB6 


JSR 


RESCUR 


B74A 


2022B9 


JSR 


ERGFDEL 


XRUN 


— Execute RUN 




B74D 


XRUN 










TEST FOR EN 


B74D 


2010B9 


JSR 


TSTEND 


B750 


B003 "B755 


BCS 


: NOFILE 


B752 


20F7BA 


JSR 


FRUN 


B755 




NOFILE 





RESTORE STMT CURRENT 



CHECK FOR END OF STMT 
IF END OP STMT, BR 
ELSE HAVE FILE NAME 



GET 1ST LINE # OF PROGRAM 



B755 A900 



B757 


85A0 


STA 


TSLNUM 


B759 


85A1 


STA 


TSLNUM+1 


B75B 


2018B8 


JSR 


SETLINE 


B75E 


20E2A9 


JSR 


TENDST 


B761 


3012 "B775 


BMI 


:RUNEND 


B763 


20F8B8 


JSR 


RUNINIT 



GET SMALLEST POSSIBLE 

LINE NUM 

X 

X 

SET UP LINE POINTERS 

TEST FOR END OF STMT TABLE 

IF AT END, BR 

CLEAR SOME STORAGE 



FALL THRU TO CLR 



XCLR — Execute CLR 



B766 




XCLR 






B766 


20C0B8 


JSR 


ZVAR 


; GO ZERO VARS 


B769 


20AFB8 


JSR 


RSTPTR 


; GO RESET STACK PTRS 


B76C 


A900 


LDA 


#0 


; CLEAR DATA VALUES 


B76E 


85B7 


STA. 


DATALN 




B770 


85B8 


STA 


DATALN+1 




B772 


85B6 


STA 


DATAD 




B774 


60 


RTS 






B77S 




: RUNEND 






B775 


4C50A0 


JMP 


SNX1 


;NO PROGRAM TO RUN 



X1F — Execute IF 



B778 

B778 200FAC 



B77B A5D5 

B77D F009 ~B788 



B77F 2010B9 
B782 B003 "B787 



B784 4CA3B6 



B787 
B787 60 



LDA 


FR0M 


BEQ 

* 


: FALSE 


* 

* 


EXPRESSION TRUE 


JSR 


TSTEND 


BCS 


:TREOS 




TRUE AND NOT EOS 


JMP 


XGOTO 




TRUE AND EOS 


:TREOS 





EVAL EXP AND GET VALUE 

INTO FR0 

GET 1ST MANTISSA BYTE 

IF = 0, # = AND IS FALSE 



TEST FOR END OF STMT 
IF AT EOS, BRANCH 



JOIN GOTO 



EXPRESSION FALSE 



B788 

B788 A59F 

B78A 85A7 

B78C 60 



: FALSE 

LDA LLNGTH 
STA NXTSTD 
RTS 



GET DISPL TO END OF LINE 
SAVE AS DISPL TO NEXT STMT 



224 



Source Code 



XEND — Execute END 



B78D 




XEND 






B78D 


20A7B7 




JSR 


STOP 




B790 


4C50A0 




JMP 


SNX1 




XSTOP — Execute STOP 








B793 




XSTOP 






B793 


20A7B7 




JSR 


STOP 


• GO SET UP STOP LINE # 








PRINT MESSAGE 




B796 


206EBD 




JSR 


PRCR 


• PRINT CR 


B799 


A9B6 




LDA 


#:MSTOP5.255 


■ SET POINTER FOR MESSAGE 


B79B 


8595 




STA 


SRCADR 


• X 


B79D 


A9B7 




LDA 


#:MSTOP/256 


• X 


B79F 


8596 




STA 


SRCADR+1 


; x 


B7A1 


2035B5 




JSR 


LPRTOKEN 


• PRINT IT 


B7A4 


4C74B9 


; 


JMP 


:ERRM2 


• PRINT REST OF MESSAGE 


B7A7 




STOP 






B7A7 


20E2A9 




JSR 


TENDST 


• GET CURRENT LINE # HIGH 


B7AA 


3007 ~B7B3 




BMI 


:STOPEND 


• IF -, THIS IS DIRECT STMT 

• DON'T STOP 


B7AC 


85BB 




STA 


STOPLN+1 


■ SAVE LINE # HIGH FOR CON 


B7AE 


88 




DEY 




• DEC INDEX 


B7AF 


B18A 




LDA 


[STMCUR],Y 


; GET LINE # LOW 


B7B1 


85BA 




STA 


STOPLN 


- SAVE FOR CON 


B7B3 




:STOPEND 






B7B3 


4C72BD 


; 


JMP 


SETDZ 


• SET L/D DEVICE =0 


B7B6 


53544F5050 


TOP DC 


'STOPPED ' 






4544A0 










XCONT — Execute Continue 






B7BE 




XCONT 






B7BE 


20E2A9 




JSR 


TENDST 


IS IT INDIRECT STMT? 


B7C1 


10F0 "B7B3 




BPL 


: STOPEND 


IF YES, BR 


B7C3 


A5BA 




LDA 


STOPLN i 


SET STOP LINE # AS LINE # 
FOR GET 


B7C5 


85A0 




STA 


TSLNUM 


X 


B7C7 


A5BB 




LDA 


STOPLN+1 


X 


B7C9 


85A1 




STA 


TSLNUM+1 


X 


B7CB 


20A2A9 




JSR 


GETSTMT 


GET ADR OF STMT WE 
STOPPED AT 


B7CE 


20E2A9 




JSR 


TENDST 


AT END OF STMT TAB ? 


B7D1 


30A2 ~B775 




BMI 


: RUNEND 




B7D3 


20DDA9 




JSR 


GETLL 


GET NEXT LINE ADDR IN CURSTM 


B7D6 


20D0A9 




JSR 


GNXTL 


X 


B7D9 


20E2A9 




JSR 


TENDST 


SEE IF WE ARE AT END OF 
STMT TABLE 


B7DC 


3097 "B775 




BMI 


: RUNEND ; 


BR IF MINUS 


B7DE 


4C1BB8 




JMP 


SETLN1 ; 


SET UP LINE POINTERS 


XTRAP — Execute TRAP 








B7E1 




XTRAP 






B7E1 


20E0AB 




JSR 


GET I NT 


CONVERT LINE # TO POSITIVE 
INT 


B7E4 


A5D4 




LDA 


FR0 ; 


SAVE LINE # LOW AS TRAP LINE 


B7E6 


85BC 




STA 


TRAPLN ; 


IN CASE OF LATER ERROR 


B7E8 


A5D5 




LDA 


FR0+1 ; 


X 


B7EA 


85BD 




STA 


TRAPLN+1 ; 


X 


B7EC 


60 




RTS 







225 



Source Code 



XON 


— Execute ON 






B7ED 




XON 




B7ED 


208AB8 


JSR 


rSAVDEX i 


B7F0 


20E9AB 


JSR 


GET1INT j 


B7F3 


A5D4 


LDA 


FR0 J 


B7F5 


F020 "B817 


BEO 


:ERV ; 


B7F7 


A4A8 


LDY 


STINDEX ; 


B7F9 


88 


DEY 




B7FA 


B18A 


LDA 


[STMCUR],Y ; 


B7FC 


C917 


CMP 


#CGTO ; 


B7FE 


F003 "B803 


BEQ 


:GO 
THIS IS ON - GOSUB: 


B800 


20CAB6 


JSR 


XGS1 ,- 



SAVE INDEX INTO LINE 

GET 1 BYTE INTEGER 

GET VALUE 

IF ZERO, FALL THROUGH TO 

NEXT STMT 

GET STMT INDEX 

BACK UP TO GOSUB/GOTO 

GET CODE 

IS IT GOTO? 

IF YES, DON'T PUSH ON 

RUN STACK 



PUT ELEMENT ON RUN STACK 



PUT ELEMENT ON RUN STACK 
FOR RETURN 



B803 




:GO 




B803 


A5D4 


LDA 


FR0 


B805 


85B3 


STA 


ONLOOP 


B807 




:ONl 




B807 


20D5AB 


JSR 


GETPINT 


B80A 


C6B3 


DEC 


ONLOOP 


B80C 


F006 ~B814 


BEQ 


:ON2 


B80E 


2010B9 


JSR 


TSTEND 


B811 


90F4 "B807 


BCC 


:ONl 


B813 


60 


RTS 




B814 




:ON2 




B814 


4CA6B6 


JMP 


XG02 


B817 




:ERV 




B817 


60 


RTS 





| GET INDEX INTO EXPRESSIONS 
; SAVE FOR LOOP CONTROL 

; GET + INTEGER 

; IS THIS THE LINE # WE WANT? 

| IF YES, GO DO IT 

) ARE THERE MORE EXPRESSIONS 
; IF YES, THEN EVAL NEXT ONE 
; ELSE FALL THROUGH TO 
NEXT STMT 

,- JOIN GOTO 



FALL THROUGH TO NEXT STMT. 



Execution Control Statement Subroutines 



SETLINE - Set Up Line Pointers 

* ON ENTRY 

* ON EXIT 



TLSNUM - LINE # 

STMCUR - CONTAIN PROPER VALUES 

LLNGTH - X 

NXTSTM - X 

CARRY SET BY GETSTMT IF LINE # NOT FOUND 



B81B 




B818 


20A2A9 


B81B 




B81B 


A002 


B81D 


B18A 


B81F 


859F 


B821 


C8 


B822 


84A7 


B824 


60 


FIXRSTK — Fix 



SETLINE 




JSR 


GETSTMT 


SETLN1 




LDY 


#2 


LDA 


[STMCUR], Y 


STA 


LLNGTH 


INY 




STY 


NXTSTD 



GET STMCUR 



GET DISP IN LINE TO LENGTH 
GET LINE LENGTH 
SET LINE LENGTH 

POINT TO NEXT STMT DISPL 
SET NXT STMT DISPL 



RTS 

Run Stack — Remove Old FORs 

* ON ENTRY A - VARIABLE # IN CURRENT FOR 
* 

* ON EXIT RUNSTK CLEAR OF ALL FOR ' S 



226 



Source Code 



B825 

B825 85C7 



B827 2081B8 



FIXRSTK 

STA ZTEMP2+1 ; SAVE VAR # OF THIS FOR 

SAVE TOP OF RUN STACK 

JSR :SAVRTOP ; SAVE TOP OF RUN STACK IN 

ZTEMP] 



B82A :FIXR 

B82A 2041B8 JSR 

B82D B008 "B837 BCS 

B82F F006 "B837 BEQ 

B831 C5C7 CMP 

B833 F00B "B840 BEQ 



B835 D0F3 ~B82A 



BNE 



POPRSTK 

:TOP 

:TOP 

ZTEMP2+1 

: FNVAR 

:FIXR 



POP AN ELEMENT FROM RUNSTK 

IF AT TOP - WE ARE DONE 

IF CC = 08 ELEMENT WAS GOSUB 

IS STK VAR # = OUR VAR #? 

IF YES, WE ARE DONE 

ELSE LOOK AT NEXT ELEMENT 



B837 




B837 


A5C4 


B839 


8590 


B83B 


A5C5 


B83D 


8591 


B83F 


60 



FOR VAR # NOT ON STACK ABOVE TOP OR GOSUB 
[RESTORE TOP OF STACK] 



LDA 
STA 
LDA 
STA 
RTS 



TEMPA 
TOPRSTK 
TEMPA+1 
TOPRSTK+1 



RESTORE TOPRSTK 

X 

X 

X 



B840 
B840 



FOR VAR # FOUND ON STACK 



: FNVAR 
RTS 



POPRSTK — Pop Element from Run Stack 



A - TYPE OF ELEMENT OR VAR # 

X - DISPL INTO LINE OF FOR/GOSUB TOKEN 

CUSET - CARRY SET STACK WAS EMPTY 

CARRY CLEAR - ENTRY POPED 

EQ SET - ELEMENT IS GOSUB 

TSLNUM - LINE # 



B841 






XPOP 


B841 






POPRSTK 


B841 


A58F 




LDA 


B843 


C591 




CMP 


B845 


9008 


"B84F 


BCC 


B847 


A58E 




LDA 


B849 


C590 




CMP 


B84B 


9002 


"B84F 


BCC 


B84D 


38 




SEC 


B84E 


60 




RTS 



B84F 

B84F A904 

B851 2072BE 

B854 A003 



B856 


B190 


B858 


85B2 


B85A 


88 


B85B 


B190 


B85D 


85A1 


B85F 


88 



TEST FOR STACK EMPTY 

RUNSTK+1 
TOPRSTK+1 
:NTOP 
RUNSTK 
TOPRSTK 
:NTOP 



GET 4 BYTE HEADER 



NTOP 
LDA 
JSR 

LDY 

LDA 
STA 
DEY 
LDA 
STA 
DEY 



GET START OF RUN STACK HIGH 
IS IT < TOP OF STACK HIGH 
IF YES, WE ARE NOT AT TOP 
GET START OF RUN STACK LOW 
IS IT < TOP OF STACK LOW 
IF YES, WE ARE NOT AT TOP 

ELSE AT TOP: SET CARRY 
RETURN 



[COMMON TO GOSUB AND FOR] 



#GFHEAD 
: RCONT 



#GFDISP 



[TOPRSTK], Y 
SVDISP 



[TOPRSTK], Y 
TSLNUM+1 



GET LENGTH OF HEADER 
TAKE IT OFF STACK 

GET INDEX TO SAVED LINE 

DISPL 

GET SAVED LINE DISPL 

SAVE 

POINT TO LINE # IN HEADER 

GET LINE # HIGH 

SAVE LINE # HIGH 

GET DISPL TO LINE # LOW 



227 



Source Code 



B860 
B862 


B190 
85A0 




LDA 
STA 




[TOPRSTK], Y 

TSLNUM 


B864 
B865 
B867 


88 

B190 

F007 "B870 




DEY 
LDA 
BEQ 


GET 


[TOPRSTK], Y 
:FND 

12 BYTE FOR 


B869 
B86A 
B86C 
B86F 


48 

A90C 
2072B8 
68 




PHA 
LDA 
JSR 
PLA 




#FBODY 
: RCONT 


B870 
B870 
B871 


18 
60 


:FND 

CLC 
RTS 






:RCONT — Contract Ru 


i Stack 








+ 
* 




ON 


ENTRY A - 


B872 
B872 
B873 
B875 


A8 

A290 

4CFBA8 


* 

: RCONT 
TAY 
LDX 
JMP 




#TOPRSTK 
CONTLOW 



GET LINE # LOW 
SAVE LINE # LOW 

POINT TO TYPE 

GET TYPE 

IF TYPE = GOSUB, 



SET ELEMENT 



SAVE VAR # 
GET # BYTES TO POP 
POP FROM RUN STACK 
GET VAR ♦ 



CLEAR CARRY [ENTRY POPPED] 



# OF BYTES TO SUBTRACT 



; Y=LENGTH 

;X = PTR TO RUN STACK 



:REXPAN — Expand Run Stack 





* ON ENTRY A - # OF BYTES TO ADD 
* 




* ON EXIT ZTEMP1 - OLD TOPRSTK 


B878 

B878 2081B8 
B87B A8 
B87C A290 
B87E 4C7FA8 


: REXPAN 

JSR : SAVRTOP 

TAY 

LDX #TOPRSTK 

JMP EXPLOW 


SAVE RUN STACK TOP 

Y=LENGTH 

X=PTR TO TOP RUN STACK 

GO EXPAND 


: SAVRTOP — Save 


Top of Run Stack in ZTEMP1 




B881 

B881 A690 
B883 86C4 
B88S A691 
B887 86C5 
B889 60 


: SAVRTOP 

LDX TOPRSTK 
STX TEMPA 
LDX TOPRSTK+1 
STX TEMPA+1 
RTS 


SAVE TOPRSTK 

X 

X 


:SAVDEX — Save Line Displacement 




B88A 

B88A A4A8 
B88C 84B3 
B88E 60 


: SAVDEX 

LDY STINDEX 
STY SAVDEX 
RTS 


GET STMT INDEX 
SAVE IT 



:MV6RS — Move 6-Byte Value to Run Stack 

* ON ENTRY X - LOCATION TO MOVE FROM 

* Y- DISPL FROM ZTEMP1 TO MOVE TO 

* ZTEMP1 - LOCATION OF RUN STK ELEMENT 



B88F 




:MV6RS 






B88F 


A906 




LDA 


#6 


GET # OF BYTES TO MOVE 


B891 


8SC6 




STA 


ZTEMP2 


SAVE AS COUNTER 


B893 




:MV 








B893 


B500 




LDA 


0,X 


GET A BYTE 


B895 


91C4 




STA 


[TEMPA], Y 


PUT ON STACK 


B897 


E8 




I NX 




POINT TO NEXT BYTE 


B898 


C8 




I NY 




POINT TO NEXT LOCATION 


B899 


C6C6 




DEC 


ZTEMP2 


DEC COUNTER 


B89B 


D0F6 "B893 




BNE 


:MV 


IF NOT = DO AGAIN 


B89D 


60 




RTS 







228 



Source Code 



:PL6RS — Pull 6 Bytes from Run Stack to FR1 

* ON ENTRY 



Y = DISPL FROM TOPRSTK TO MOVE PROM 
TOPRSTK - START OF ELEMENT 



B89E 




:PL6RS 




B89E 


A906 


LDA 


#6 


B8A0 


85C6 


STA 


ZTEMP2 


B8A2 


A2E0 


LDX 


#FR1 


B8A4 




:PL 




B8A4 


B190 


LDA 


[TOPRSTK], Y 


B8A6 


9500 


STA 


0,X 


B8A8 


E8 


I NX 




B8A9 


C8 


I NY 




B8AA 


C6C6 


DEC 


ZTEMP2 


B8AC 


D0F6 "B8A4 BNE 


:PL 


B8AE 


60 


RTS 





RSTPTR — Reset Stack Pointers [STARP and RUNSTK] 



B8AF 




RSTPTR 




B8AF 


A58C 


LDA 


STARP 


B8B1 


858E 


STA 


RUNSTK 


B8B3 


8590 


STA 


MEMTOP 


B8B5 


850E 


STA 


APHM 


B8B7 


A58D 


LDA 


STARP+1 


B8B9 


858F 


STA 


RUNSTK+1 


B8BB 


8591 


STA 


MEMTOP+1 


B8BD 


850F 


STA 


APHM+1 


B8BF 


60 


RTS 





GET # OF BYTES TO MOVE 
SAVE AS COUNTER 



GET A BYTE 

SAVE IN Z PAGE 

INC TO NEXT LOCATION 

INC TO NEXT BYTE 

DEC COUNTER 

IP NOT =0, DO AGAIN 



GET BASE OF STR/ARRAY 

SPACE LOW 

RESET 

SET APPLICATION HIMEM 

GET BASE STR/ARRAY SPACE 

HIGH 

RESET 

X 

SET APPLICATION HIMEM 



ZVAR — Zero Variable 

B8C0 ZVAR 



B8C0 


A686 




LDX 


WTP 


MOVE VARIABLE TABLE POINTER 


B8C2 


86F5 




STX 


ZTEMP1 


X 


B8C4 


A487 




LDY 


WTP+1 


X 


B8C6 


84F6 




STY 


ZTEMP1+1 
ARE WE AT END OF TABI 


X 


B8C8 






ZVAR1 






B8C8 


A6F6 




LDX 


ZTEMP1+1 


GET NEXT VARIABLE ADDR HIGH 


B8CA 


E489 




CPX 


ENDWT+1 


IS IT < END VALUE HIGH 


B8CC 


9007 


"B8D5 


BCC 


:ZVAR2 


IF YES, MORE TO DO 


B8CE 


A6F5 




LDX 


ZTEMP1 


GET NEXT VARIABLE ADDR LOW 


B8D0 


E488 




CPX 


ENDWT 


IS IT < END VALUE LOW 


B8D2 


9001 


"B8D5 


BCC 


:ZVAR2 


IP YES, MORE TO DO 


B8D4 


60 




RTS 


ZERO A VARIABLE 


ELSE, DONE 


B8D5 






ZVAR2 






B8D5 


A000 




LDY 


#0 


TURN OFF 


B8D7 


B1F5 




LDA 


[ZTEMP1], Y 


DIM FLAG 


B8D9 


29FE 




AND 


#$FE 




B8DB 


91F5 




STA 


[ZTEMP1], Y 




B8DD 


A002 




LDY 


#2 


INDEX PAST VARIABLE HEADER 


B8DF 


A206 




LDX 


#6 


GET # OF BYTES TO ZERO 


B8E1 


A900 




LDA 


#0 


CLEAR A 


B8E3 






ZVAR3 






B8E3 


91F5 




STA 


[ZTEMP1],Y 


ZERO BYTE 


B8E5 


C8 




I NY 




POINT TO NEXT BYTE 


B8E6 


CA 




DEX 




DEC POINTER 


B8E7 


D0FA 


"B8E3 


BNE 


:ZVAR3 


IF NOT = 0, ZERO NEXT BYTE 



229 



Source Code 



B8E9 A5F5 

B8EB 18 

B8EC 6908 

B8EE 85P5 

B8F0 A5F6 

B8F2 6900 

B8F4 85F6 

B8F6 D0D0 "B8C8 



LDA 


ZTEMP1 


; GET CURRENT VARIABLE 
POINTER LOW 


CLC 






ADC 


#8 


I INCR TO NEXT VARIABLE 


STA 


ZTEMP1 


; SAVE NEW VARIABLE POINTER 
LOW 


LDA 


ZTEMP1+1 


; GET CURRENT VARIABLE 
POINTER HIGH 


ADC 


#0 


; ADD IN CARRY 


STA 


ZTEMP1+1 


; SAVE NEW VARIABLE POINTER 
HIGH 


BNE 


:ZVAR1 


; UNCONDITIONAL BRANCH 



RUNINIT — Initialize Storage Locations for RUN 



B8F8 




RUNINIT 










B8F8 


A000 




LDY 


#0 






CLEAR A 


B8FA 


84BA 




STY 


STOPLN 






CLEAR LINE # STOPPED AT 


B8FC 


84BB 




STY 


STOPLN+1 






X 


B8FE 


84B9 




STY 


ERRNUM 






CLEAR ERROR # 


B900 


84FB 




STY 


RADFLG 






CLEAR FLAG TOR TRANSENDENTALS 


B902 


84B6 




STY 


DATAD 






CLEAR DATA POINTERS 


B904 


84B7 




STY 


DATALN 






X 


B906 


84B8 




STY 


DATALN+1 






X 


B908 


88 




DEY 










B909 


84BD 




STY 


TRAPLN+1 






SET TRAP FLAG TO NO TRAP 


B90B 


8411 




STY 


BRKBYT 






SET BRK BYTE OFF [$FF] 


B90D 


4C41BD 




JMP 


CLSALL 






GO CLOSE ALL DEVICES 


TSTEND - Test for 


End of Statem 


ent 












* 


ON 


EXIT CC 


SET 








* 




CARRY 


SET 


- END OF STMT 






* 




CARRY 


CLE) 


VR - NOT END OF STMT 



B910 




TSTEND 




B910 


A6A8 


LDX 


STINDEX 


B912 


E8 


I NX 




B913 


E4A7 


CPX 


NXTSTD 


B915 


60 


RTS 





Error Messages 



Error Message Routine 



B916 


E6B9 


ERRNSF 


INC 


ERRNUM 


B918 


E6B9 


ERRDNO 


INC 


ERRNUM 


B91A 


E6B9 


ERRPTL 


INC 


ERRNUM 


B91C 


E6B9 


ERSVAL 


INC 


ERRNUM 


B91E 


E6B9 


XERR 


INC 


ERRNUM 


B920 


E6B9 


ERBRTN 


INC 


ERRNUM 


B922 


E6B9 


ERGFDE 


INC 


ERRNUM 


B924 


E6B9 


ERLTL 


INC 


ERRNUM 


B926 


E6B9 


ERNOFOR 


INC 


ERRNUM 


B928 


E6B9 


ERNOLN 


INC 


ERRNUM 


B92A 


E6B9 


EROVFL 


INC 


ERRNUM 


B92C 


E6B9 


ERRAOS 


INC 


ERRNUM 


B92E 


E6B9 


ERRDIM 


INC 


ERRNUM 


B930 


E6B9 


ERRINP 


INC 


ERRNUM 


B932 


E6B9 


ERRLN 


INC 


ERRNUM 


B934 


E6B9 


ERROOD 


INC 


ERRNUM 


B936 


E6B9 


ERRSSL 


INC 


ERRNUM 


B938 


E6B9 


ERRVSF 


INC 


ERRNUM 


B93A 


E6B9 


ERVAL 


INC 


ERRNUM 


B93C 


E6B9 


MEMFULL 


INC 


ERRNUM 


B93E 


E6B9 


ERON 


INC 


ERRNUM 



FILE NOT SAVE FILE 

#DN0 > 7 

LOAD PGM TOO BIG 

STRING NOT VALID 
EXECUTION OF GARBAGE 

BAD RETURNS 

GOSUB/FOR LINE DELETED 

LINE TO LONG 

NO MATCHING FOR 

LINE NOT FOUND [GOSUB/GOTO] 

FLOATING POINT OVERFLOW 

ARG STACK OVERFLOW 

ARRAY/STRING DIM ERROR 

INPUT STMT ERROR 
VALUE NOT <32768 

READ OUT OF DATA 

STRING LENGTH ERROR 

VARIABLE TABLE FULL 

VALUE ERROR 

MEMORY FULL 

NO LINE # FOR EXP IN ON 



230 



Source Code 



Error Routine 

B940 

B940 A900 

B942 8DFE02 

B945 20A7B7 

B948 A5BD 

B94A 3015 "E 



B94C 85A1 



B94E 


A5BC 


B950 


85A0 


B952 


A980 


B954 


85BD 


B956 


A5B9 


B958 


85C3 


B95A 


A900 


B95C 


85B9 


B95E 


4CAEB6 



ERROR 






LDA 




#0 


STA 




DSPPLG 


JSR 




STOP 


LDA 




TRAPLN+1 


BMI 




:ERRM1 


* 


TRAP SET - GO TO 


STA 




TSLNUM+1 


LDA 




TRAPLN 


STA 




TSLNUM 


LDA 




#$80 


STA 




TRAPLN+1 


LDA 




ERRNUM 


STA 




ERRSAV 


LDA 




#0 


STA 




ERRNUM 


JMP 




XGOl 


* 
* 


NO 


TRAP - PRINT I 



; FLAG 

; SET LINE # STOPPED AT 

; GET TRAP LINE # HIGH 

| IF NO LINE # PRINT MESSAGE 

SPECIFIED LINE # 

; SET TRAP LINE # HIGH FOR 

GET STMT 
; GET TRAP LINE # LOW 
; SET FOR GET STMT 

; TURN OFF TRAP 



GET ERROR # 
SAVE IT 
CLEAR 
ERROR# 
JOIN GOTO 



B961 



Print Error Message Part 1 [**ERR] 



B961 


206EBD 


JSR 


PRCR 


B964 


A937 


LDA 


#CERR 


B966 


203DB6 


JSR 


LSTMC 


Print Error Number 






B969 


A5B9 


LDA 


ERRNUM 


B96B 


85D4 


STA 


FR0 


B96D 


A900 


LDA 


#0 


B96F 


85D5 


STA 


FR0+1 


B971 


209CB9 


JSR 


:PRINUM 


B974 




:ERRM2 




B974 


20E2A9 


JSR 


TENDST 


B977 


3019 ~B992 


BMI 


:ERRDONE 



PRINT CR 

GET TOKEN FOR ERROR 

GO PRINT CODE 



GET ERROR 

SET ERROR 

SET ERROR 
X 



# OF FR0 AS INTEGER 

# HIGH 



GO PRINT ERROR # 



TEST FOR DIRECT STMT 
IF DIRECT STMT, DONE 



Print Message Part 2 [AT LINE] 



B979 


A9AE 


B97B 


8595 


B97D 


A9B9 


B97F 


8596 


B981 


2035B5 


Print Line Number 


B984 


A001 


B986 


B18A 


B988 


85D5 


B98A 


88 


B9SB 


B18A 


B98D 


85D4 



B98F 209CB9 



LDA 


#:ERRMS&255 


STA 


SRCADR 


LDA 


#:ERRMS/256 


STA 


SRCADR+1 


JSR 


LPRTOKEN 


LDY 


#1 


LDA 


[STMCUR], Y 


STA 


FR0+1 


DEY 




LDA 


[STMCUR], Y 


STA 


FR0 


JSR 


: PRINUM 



SET POINTER TO MSG FOR PRINT 

X 

X 

X 



SET DISPL 
GET LINE # HIGH 

SET IN FR0 FOR CONVERT 

GET CURRENT LINE # LOW 
GET UNUSED LINE # LOW 

SET IN FR0 LOW FOR CONVERT 



PRINT LINE # 



231 



Source Code 



B992 




:ERRDONE 




B992 


206EBD 


JSR 


PRCR 


B995 


A900 


LDA 


#0 


B997 


85B9 


STA 


ERRNUM 


B999 


4C60A0 


JMP 


SYNTAX 



PRINT CR 
CLEAR A 
CLEAR ERROR # 



Print Integer Number in FRO 



B99C 




:PRINUM 




B99C 


20AAD9 


JSR 


CVIFP 


B99F 


20E6D8 


JSR 


CVFASC 


B9A2 


A5F3 


LDA 


INBUFF 


B9A4 


8595 


STA 


SRCADR 


B9A6 


A5F4 


LDA 


INBUFF+1 


B9A8 


8596 


STA 


SRCADR+1 


B9AA 


2035B5 


JSR 


LPRTOKEN 


B9AD 


60 


RTS 





204154204C 
494E45A0 



ERRMS DC 



CONVERT TO FLOATING POINT 

CONVERT TO ASCII 

GET ADR OF # LOW 

SET FOR PRINT ROUTINE 

GET ADR OF # HIGH 

SET FOR PRINT ROUTINE 
GO PRINT ERROR # 



Execute Graphics Routines 



XSETCOLOR- 


-Execute SET COLOR 




B9B7 






XSETCOLOR 






B9B7 


20E9AB 




JSR 


GET1INT 


; GET REGISTER # 


B9BA 


A5D4 




LDA 


FR0 


; GET # 


B9BC 


C905 




CMP 


#5 


; IS IT <5? 


B9BE 


B01A "B9DA 


BCS 


:ERCOL 


; IF NOT, ERROR 


B9C0 


48 




PHA 




; SAVE 


B9C1 


20E0AB 




JSR 


GETINT 


j GET VALUE 


B9C4 


A5D4 




LDA 


FR0 


; GET VALUE* 16+6 


B9C6 






AS LA 




T X 


B9C6 


+0A 




ASL 


A 




B9C7 






AS LA 




; X 


B9C7 


+0A 




ASL 


A 




B9C8 






ASLA 




; X 


B9C8 


+0A 




ASL 


A 




B9C9 






ASLA 




r X 


B9C9 


+0A 




ASL 


A 




B9CA 


48 




PHA 




; SAVE ON STACKS 


B9CB 


20E0AB 




JSR 


GETINT 


; GET VALUE 3 


B9CE 


68 




PLA 




; GET VALUE 2*16 FROM STACK 


B9CF 


18 




CLC 






B9D0 


6 5D4 




ADC 


FR0 


; ADD IN VALUE 3 


B9D2 


A8 




TAY 




; SAVE VALUE 2*16 + VALUE 5 


B9D3 


6 8 




PLA 




; GET INDEX 


B9D4 


AA 




TAX 




; PUT IN X 


B9D5 


98 




TYA 




; GET VALUE 


B9D6 


9DC402 




STA 


CREGS.X 


;SET VALUE IN REGS 


B9D9 


60 




RTS 






B9DA 






:ERSND 






B9DA 






:ERCOL 






B9DA 


203AB9 




JSR 


ERVAL 




XSOUND — Execute SOUND 






B9DD 






XSOUND 






B9DD 


20E9AB 




JSR 


GET1INT 


; GET 1 BYTE INTEGER 


B9E0 


A5D4 




LDA 


FR0 


; X 


B9E2 


C904 




CMP 


#4 


; IS IT <4? 


B9E4 


B0F4 "B9DA 


BCS 


:ERSND 


; IF NOT, ERROR 



232 



Source Code 



B9E6 

B9E6 +0A 

B9E7 48 

B9E8 A900 

B9EA 8D08D2 

B9ED A903 

B9EP 8D0FD2 



B9F2 
B9F5 
B9F6 
B9F7 
B9F8 
B9FA 



20E0AB 

68 

48 

AA 

A5D4 

9D00D2 



B9FD 
BA00 
BA02 

BA02 +0A 
BA03 

BA03 +0A 
BA04 

BA04 +0A 
BA05 
BA05 +0A 



20E0AB 
A5D4 



BA07 
BA0A 
BA0B 
BA0C 
BA0D 
BA0E 
BA0F 
BA10 
BA12 
BA15 



20E0AB 

68 

A 8 

68 

AA 

98 

18 

65D4 

9D01D2 

60 



ASLA 




ASL 


A 


PHA 




LDA 


#0 


STA 


SREG1 


LDA 


#3 


STA 


SKCTL 


JSR 


GETINT 


PLA 




PHA 




TAX 




LDA 


FR0 


STA 


SREG2.X 


JSR 


GETINT 


LDA 


FR0 


ASLA 




ASL 


A 


ASLA 




ASL 


A 


ASLA 




ASL 


A 


ASLA 




ASL 


A 


PHA 




JSR 


GETINT 


PLA 




TAY 




PLA 




TAX 




TYA 




CLC 




ADC 


FR0 


STA 


SREG3.X 


RTS 





| GET VALUE *2 



SET TO ZERO 
X 



GET EXP2 

GET INDEX 

SAVE AGAIN 

PUT IN INDEX REG 

GET VALUE 

SAVE IT 

GET EXP 3 
GET 16*EXP3 
X 



SAVE IT 

GET EXP4 
GET 16*EXP3 
SAVE IT 
GET INDEX 
PUT IN X 
GET EXP3*16 

GET 16*EXP3+EXP4 

STORE IT 



XPOS — Execute POSITION 



BA16 
BA16 
BA19 
BA1B 
BA1D 
BA1F 



20E0AB 
A5D4 

8555 
A5D5 
8556 



BA21 20E9AB 

BA24 A5D4 

BA26 8554 

BA28 60 



BA29 
BA29 
BA2C 
BA2E 
BA30 



20E0AB 
A5D4 
85C8 
60 



BA31 

BA31 2016BA 

BA34 A5C8 

BA36 8DFB02 



JSR 


GETINT 


LDA 


FR0 


STA 


SCRX 


LDA 


FR0+1 


STA 


SCRX+1 


JSR 


GET1INT 


LDA 


FR0 


STA 


SCRY 


RTS 




COLOR 




XCOLOR 




JSR 


GETINT 


LDA 


FR0 


STA 


COLOR 


RTS 




e DRAWTO 




XDRAWTO 




JSR 


XPOS 


LDA 


COLOR 


STA 


SVCOLOR 



GET INTEGER INTO FR0 

SET X VALUE 

X 

X 

X 

SET Y VALUE 

X 

X 



GET INTEGER INTO FR0 



GET X,Y POSITION 
GET COLOR 



233 



Source Code 



BA39 


A911 


BA3B 


A206 


BA3D 


20C4BA 


BA40 


A90C 


BA42 


9D4A03 


BA45 


A900 


BA47 


9D4B03 


BA4A 


2024BD 


BA4D 


4CB3BC 


XCR- 


- Execul 


BA50 




BA50 


A206 


BA52 


86C1 


BA54 


20F1BC 


BA57 


20E0AB 


BA5A 


A27 3 


BA5C 


A0BA 


BA5E 


86F3 


BA60 


84F4 


BA62 


A206 


BA64 


A5D4 


BA66 


29F0 


BA68 


491C 


BA6A 


A8 


BA6B 


A5D4 


BA6D 


20D1BB 


BA70 


4CB3BC 



LDA 


tICDRAW 


LDX 


#6 


JSR 


GLPCX 


LDA 


#$0C 


STA 


ICAUX1.X 


LDA 


#0 


STA 


ICAUX2.X 


JSR 


107 


JMP 


IOTEST 



LDX 


#6 


STX 


IODVC 


JSR 


CLSYS1 


JSR 


GETINT 


LDX 


#SSTR&255 


LDY 


#SSTR/256 


STX 


INBUFF 


STY 


INBUFF+1 


LDX 


#6 


LDA 


FR0 


AND 


#?F0 


EOR 


#ICGR 


TAY 




LDA 


FR0 


JSR 


SOPEN 


JMP 


IOTEST 



GET COMMAND 
SET DEVICE 
SET THEM 

SET AUX 1 

SET AUX 2 



GET DEVICE 
SAVE DEVICE # 
GO CLOSE IT 
GET INTEGER INTO FR0 

SET INBUFF TO POINT 
TO FILE SPEC STRING 
X 
X 

GET DEVICE # 
SET SOME BITS FOR GRAPHICS 



GET AUX2 [GRAPHICS TYPE] 

OPEN 

TEST I/O OK 



BA73 533A9B 



XPLOT — Execute PLOT 



BA76 




XPLOT 




BA76 


2016BA 


JSR 


XPOS 


BA79 


A5C8 


LDA 


COLOR 


BA7B 


A206 


LDX 


#6 


BA7D 


4CA1BA 


JMP 


PRCX 



SET X,Y POSITION 

GET COLOR 
GET DEVICE # 
GO PRINT IT 



Input/Output Routines 

LOCAL 



GETLINE - Get a Line of Input 











GLINE - GET LINE L PROMPT ONLYJ 
GNLINE - GET NEW LINE [CR, PROMPT] 


BA80 






ONLINE 






BA80 


A6B4 




LDX 


ENTDTD 


IF ENTER DEVICE NOT ZERO 


BA82 


D00E * 


BA92 


BNE 


GLGO 


THEN DO PROMPT 


BA84 


A99B 




LDA 


#CR 


PUT EOL 


BA86 


209FBA 




JSR 


PUTCHAR 




BA89 






GLINE 






BA89 


A6B4 




LDX 


ENTDTD 


IF ENTER DEVICE NOT ZERO 


BA8B 


D005 " 


BA92 


BNE 


GLGO 


THEN DON'T PROMPT 


BA8D 


A5C2 




LDA 


PROMPT 


PUT PROMPT 


BA8F 


209FBA 




JSR 


PUTCHAR 




BA92 






GLGO 






BA92 


A6B4 




LDX 


ENTDTD 




BA94 


A905 




LDA 


tICGTR 





234 



Source Code 



BA96 


20C4BA 


BA99 


200ABD 


BA9C 


4CB3BC 


PUTCHAR — P 


BA9F 




BA9F 




BA9F 


A6B5 


BAA1 




BAA1 


48 


BAA 2 


20C6BA 


BAA 5 


BD4A0 3 


BAA 8 


852A 


BAAA 


BD4B03 


BAAD 


852B 


BAAF 


68 


BAB0 


A8 


BAB1 


20B8BA 


BAB 4 


98 


BAB 5 


4CB6BC 


BAB 8 




BAB 8 


BD4703 


BABB 


48 


BABC 


BD4603 


BABF 


48 


BAC0 


98 


BAC1 


A092 


BAC3 


60 


BAC4 


85C0 


BAC6 




BAC6 


86C1 


BAC8 


4CA6BC 



JSR 


GLPCX 


JSR 


101 


JMP 


I0TEST 



Put One Character to List Device 

PRCHAR 
PUTCHAR 

LDX LISTDTD 
PRCX 

PHA 

JSR 



GLPX 



GO DO I/O 

GO TEST RESULT 



GET LIST DEVICE 



SAVE 10 BYTE 
SET DEVICE 



LDA 
STA 
LDA 
STA 

PLA 
TAY 
JSR 



ICAUX1.X r SET UP ZERO PAGE IOCB 

ICAUX1-I0CB+ZICB ; X 
ICAUX2.X ; X 

ICAUX2-IOCB+ZICB ; X 



:PDUM 



RETURN HERE FROM ROUTINE 
TYA ; TEST STATUS 

JMP I0TES2 



:PDUM 






LDA 




ICPUT+l.X 


PHA 






LDA 




ICPUT.X 


PHA 






TYA 






LDY 




#?92 


RTS 






GLPCX 


STA 


IOCMD 


GLPX 






STX 




IODVC 


JMP 




LDDVX 



GO TO PUT ROUTINE 
X 
X 
X 
X 
LOAD VALUE FOR CIO ROUTINE 



AS I/O DEVICE 
LOAD DEVICE X 



XENTER — Execute ENTER 



BACB 




XENTER 






BACB 


A904 


LDA 


#$04 


OPEN INPUT 


BACD 


20DDBA 


JSR 


ELADVC 


• GO OPEN ALT DEVICE 


BAD0 


85B4 


STA 


ENTDTD 


SET ENTER DEVICE 


BAD2 


4C60A0 


JMP 


SYNTAX 




FLIST 


— Open 


LIST File 






BAD5 




FLIST 






BAD5 


A908 


LDA 


#$08 


OPEN OUTPUT 


BAD7 


20DDBA 


JSR 


ELADVC 


GO OPEN ALT DEVICE 


BADA 


85B5 


STA 


LISTDTD 


SET LIST DEVICE 


BADC 


60 


RTS 




DONE 


BADD 




ELADVC 






BADD 


48 


PHA 






BADE 


A007 


LDY 


#7 


USE DEVICE 7 


BAE0 


84C1 


STY 


IODVC 


SET DEVICE 


BAE2 


20A6BC 


JSR 


LDDVX 


BEFORE 


BAE5 


A90C 


LDA 


tICCLOSE 


GO CLOSE DEVICE 


BAE7 


2026BD 


JSR 


108 


OPEN OF NEW ONE 


BAEA 


A003 


LDY 


#ICOI0 


CMD IS OPEN 


BAEC 


84C0 


STY 


IOCMD 




BAEE 


68 


PLA 






BAEF 


A000 


LDY 


#0 


GET AUX2 


BAF1 


20FBBB 


JSR 


X0P2 


GO OPEN 



235 



Source Code 



BAP 4 
BAF6 



A907 
60 



LDA 
RTS 



#7 



RUN from File 



BAF7 
BAF9 



A9FF 
D002 



FRUN LDA 

BNE 



#$FF 



XLOAD — Execute LOAD Command 



BAFB 




XLOAD 




BAFB 


A900 


LDA 


#0 


BAFD 


48 


:LD0 PHA 




BAFE 


A904 


LDA 


#04 '; 


BB00 


20DDBA 


JSR 


ELADVC 


BB03 


68 


PLA 




BB04 




XLOAD1 




BB04 


48 


PHA 




BB05 


A907 


LDA 


#ICGTC ; 


BB07 


85C0 


STA 


IOCMD 


BB09 


85CA 


STA 


LOADFLG r 


BB0B 


20A6BC 


JSR 


LDDVX ; 


BB0E 


A00E 


LDY 


#ENDSTAR-OUTBUFF 


BB10 


2010BD 


JSR 


103 


BB13 


20B3BC 


JSR 


IOTEST 


BB16 


AD8005 


LDA 


MISCRAM+OUTBUFF ; 


BB19 


0D8105 


ORA 


MlSCRAM+OUTBUFF+1 


BB1C 


D038 ~BB56 


BNE 


: LDFER 


BB1E 


A28C 


LDX 


#STARP ; 


BB20 


18 


:LD1 CLC 




BB21 


A580 


LDA 


OUTBUFF 


BB23 


7D0005 


ADC 


MISCRAM.X ; 


BB26 


A8 


TAY 




BB27 


A581 


LDA 


OUTBUFF+1 


BB29 


7D0105 


ADC 


MISCRAM+l.X 


BB2C 


CDE602 


CMP 


HIMEM+1 ; 


BB2F 


900A "BB3B 


BCC 


:LD3 ; 


BB31 


D005 "BB38 


BNE 


:LD2 ; 


BB33 


CCE502 


CPY 


HIMEM 


BB36 


9003 "BB3B 


BCC 


:LD3 


BB38 


4C1AB9 


:LD2 JMP 


ERRPTL 


BB3B 


9501 


:LD3 STA 


1,X 


BB3D 


9400 


STY 


0,X 


BB3F 


CA 


DEX 




BB40 


CA 


DEX 




BB41 


E082 


CPX 


#VNTP ; 


BB43 


B0DB "BB20 


BCS 


: LD1 ,• 


BB45 


2088BB 


JSR 


:LSBLK ; 


BB48 


2066B7 


JSR 


XCLR i 


BB4B 


A900 


LDA 


#0 ! 


BB4D 


85CA 


STA 


LOADFLG ; 


BB4F 


68 


PLA 




BB50 


F001 "BB53 


BEQ 


:LD4 i 


BB52 


60 


RTS 




BB53 




:LD4 




BB53 


4C50A0 


JMP 


SNX1 ; 


BB56 




: LDFER 




BB56 


A900 


LDA 


#0 


BB58 


85CA 


STA 


LOADFLG 


BB5A 


2016B9 


JSR 


ERRNSF 



LOAD DEVICE 
AND RETURN 



SET RUN MODE 



SET LOAD MODE 

SAVE R/L TYPE 

GO OPEN FOR INPUT 

THE SPECIFIED DEVICE 

GET R/L TYPE 



SAVE R/L TYPE 

CMD IS GET TEXT CHARS 

SET LOAD IN PROGRESS 

LOAD DEVICE X REG 
r Y=REC LENGTH 
GO GET TABLE BLOCK 
TEST I/O 
IF FIRST 2 
r BYTES NOT ZERO 
THEN NOT SAVE FILE 

START AT STARP DISPL 

; ADD LOMEM TO 

LOAD TABLE DISPL 



IF NEW VALUE NOT 
LESS THEN HIMEM 
THEN ERROR 



ELSE SET NEW TABLE VALUE 

DECREMENT TO PREVIOUS TBL 
ENTRY 

IF NOT AT LOWER ENTRY 
THEN CONTINUE 

LOAD USER AREA 

EXECUTE CLEAR 

RESET LOAD IN PROGRESS 

X 

LOAD R/S STATUS 

BR IF LOAD 

RETURN TO RUN 

GO TO SYNTAX 



RESET LOAD IN PROGRESS 



NOT SAVE FILE 



236 



Source Code 



XSAVE — Execute SAVE Command 



BB5D 




XSAVE 




BB5D 


A908 


LDA 


#08 


BB5F 


20DDBA 


JSR 


ELADVC 


BB62 




XSAVE 1 




BB62 


A90B 


LDA 


fICPTC 


BB64 


85C0 


STA 


IOCMD 


BB66 


A280 


LDX 


#OUTBUFF 


BB68 


38 


:SV1 SEC 




BB69 


B500 


LDA 


0,X 


BB6B 


E580 


SBC 


OUT BUFF 


BB6D 


9D0005 


STA 


MISCRAM,X 


BB70 


E8 


INX 




BB71 


B500 


LDA 


0,X 


BB73 


E581 


SBC 


OUTBUFF+1 


BB75 


9D0005 


STA 


MISCRAM.X 


BB78 


E8 


INX 




BB79 


E08E 


CPX 


#ENDSTAR 


BB7B 


90EB "BB68 


BCC 


iSVl 


BB7D 


20A6BC 


JSR 


LDDVX 


BB80 


A00E 


LDY 


#ENDSTAR-OUTBUFF 


BB82 


2010BD 


JSR 


103 


BB85 


20B3BC 


JSR 


IOTEST 


LSBLK 


— LOAD or 


SAVE User Area 


as a Block 


BB88 




:LSBLK 




BB88 


20A6BC 


JSR 


LDDVX 


BB8B 


A582 


LDA 


VNTP 


BB8D 


85F3 


STA 


INBUFF 


BB8F 


A583 


LDA 


VNTP+1 


BB91 


85F4 


STA 


INBUFF+1 


BB93 


AC8D05 


LDY 


MISCRAM+STARP+1 


BB96 


88 


DEY 




BB97 


98 


TYA 




BB98 


AC8C05 


LDY 


MISCRAM+STARP 


BB9B 


2012BD 


JSR 


104 


BB9E 


20B3BC 


JSR 


IOTEST 


BBA1 


4CF1BC 


JMP 


CLSYS1 



GO OPEN FOR OUTPUT 
THE SPECIFIED DEVICE 



I/O CMD IS PUT TEXT CHARS 
SET I/O CMD 

MOVE RAM TABLE PTRS 
[OUTBUFF THRU ENSTAR] 
TO LBUFF 
AS DISPLACEMENT 
FROM LOW MEM 



OUTPUT LBUFF 
; FOR PROPER LENGTH 

TEST GOOD I/O 



LOAD DEVICE X REG 
SET VAR NAME TBL PTR 
AS START OF BLOCK ADR 



; A,Y = BLOCK LENGTH 

; GO DO BLOCK I/O 
;G0 CLOSE DEVICE 



XCSAVE — Execute CSAVE 



BBA4 

BBA4 A908 

BBA6 20B6BB 



XCSAVE 
LDA 
JSR 



#8 
COPEN 



GET OPEN FOR OUTPUT 
OPEN CASSETTE 



BBA9 4C62BB JMP 

XCLOAD — Execute CLOAD 



BBAC 


A904 


LDA 


#4 


BBAE 


20B6BB 


JSR 


COPEN 


BBB1 


A900 


LDA 


#0 


BBB3 


4C04BB 


JMP 


XL0AD1 



GET OPEN FOR OUTPUT 
OPEN CASSETTE 



GET LOAD TYPE 
DO LOAD 



COPEN — OPEN Cassette 







* 


ON ENTRY: A - 






* 
* 


ON EXIT: A - 


BBB6 




COPEN 




BBB6 


48 


PHA 




BBB7 


A2CE 


LDX 


#:CSTR6,255 


BBB9 


86F3 


STX 


INBUFF 



TYPE OF OPEN [IN OR OUT] 
DEVICE #7 



237 



Source Code 



BBBB 


A2BB 


LDX 


#:CSTR/256 




BBBD 


86F4 


STX 


INBUFF+1 




BBBF 


A207 


LDX 


#7 




BBC1 


68 


PLA 






BBC2 


A8 


TAY 




; SET COMMAND TYPE 


BBC3 


A980 


LDA 


#$80 


; GET AUX 2 


BBC 5 


20D1BB 


JSR 


SOPEN 


; GO OPEN 


BBC8 


20B3BC 


JSR 


IOTEST 




BBCB 


A907 


LDA 


#7 


; GET DEVICE 


BBCD 


60 


RTS 







BBCE 433A9B 



SOPEN — OPEN System Device 



ON ENTRY X - DEVICE 
Y - AUX1 
A - AUX2 
INBUFF - POINTS TO FILE SPEC 



BBD1 




SOPEN 






BBD1 


48 


PHA 




SAVE AUX2 


BBD2 


A903 


LDA 


IICOIO 


GET COMMAND 


BBD4 


20C4BA 


JSR 


GLPCX 


GET DEVICE/COMMAND 


BBD7 


68 


PLA 




SET AUX2 & AUX 1 


BBD8 


9D4B03 


STA 


ICAUX2.X 


X 


BBDB 


98 


TYA 






BBDC 


9D4A03 


STA 


ICAUX1,X 




BBDF 


2019BD 


JSR 


105 


DO COMMAND 


BBE2 


4C51DA 


JMP 


INTLBF 


RESET INBUFF 



XXIO — Execute XIO Statement 

XXIO 



BBE5 

BBE5 2004BD 

BBE8 4CEDBB 



JSR GIOCMD 
JMP X0P1 



XOPEN — Execute OPEN Statement 



GET THE COMMAND BYTE 
CONTINUE AS IF OPEN 



BBEB 




XOPEN 






BBEB 


A903 


LDA 


#IC0IO 


; LOAD OPEN CODE 


BBED 


85C0 


X0P1 STA 


IOCMD 




BBEF 


209FBC 


JSR 


GIODVC 


; GET DEVICE 


BBF2 


2004BD 


JSR 


GIOCMD 


; GET AUX1 


BBF5 


48 


PHA 






BBF6 


2004BD 


JSR 


GIOCMD 


,- GET AUX2 


BBF9 


A8 


TAY 




; AUX2 IN Y 


BBFA 


68 


PLA 




; AUX1 IN A 


BBFB 




X0P2 






BBFB 


48 


PHA 




; SAVE AUX1 


BBFC 


98 


TYA 






BBFD 


48 


PHA 




; SAVE AUX2 


BBFE 


20E0AA 


JSR 


EXEXPR 


; GET FS STRING 


BC01 


2079BD 


JSR 


SETSEOL 


; GIVE STRING AN EOL 


BC04 


20A6BC 


JSR 


LDDVX 


; LOAD DEVICE X REG 


BC07 


68 


PLA 






BC08 


9D4B03 


STA 


ICAUX2,X 


; SET AUX 2 


BC0B 


68 


PLA 




; GET AUX 1 


BC0C 


9D4A03 


STA 


ICAUX1.X 




BC0F 


200ABD 


JSR 


101 


r GO DO I/O 


BCI2 


2099BD 


JSR 


RSTSEOL 


; RESTORE STRING EOL 



238 



Source Code 



BC15 


2051DA 


JSR 


INTLBF 




BC18 


4CB3BC 


JMP 


IOTEST 


GO TEST I/O STATU 


XCLOSE — Execute CLOSE 






BC1B 




XCLOSE 






BC1B 


A90C 


LDA 


#ICCLOSE 


CLOSE CMD 


GDVCIO — General Device I/O 






BC1D 




GDVCIO 






BC1D 


85C0 


STA 


IOCMD 


SET CMD 


BC1F 


209FBC 


JSR 


GIODVC 


GET DEVICE 


BC22 


2024BD 


GDI01 JSR 


107 


GO DO I/O 


BC25 


4CB3BC 


JMP 


IOTEST 


GO TEST STATUS 


XSTATUS — Execute STATUS 






BC28 




XSTATUS 






BC28 


209FBC 


JSR 


GIODVC 


GET DEVICE 


BC2B 


A90D 


LDA 


KICSTAT 


STATUS CMD 


BC2D 


2026BD 


JSR 


108 


GO GET STATUS 


BC30 


20FBBC 


JSR 


LDIOSTA 


LOAD STATUS 


BC33 


4C2DBD 


JMP 


ISVAR1 


GO SET VAR 


XNOTE — Execute NOTE 






BC36 




XNOTE 






BC36 


A926 


LDA 


#$26 


NOTE CMD 


BC38 


201DBC 


JSR 


GDVCIO 


GO DO 


BC3B 


BD4C03 


LDA 


ICAUX3,X 


GET SECTOR St/. LO 


BC3E 


BC4D03 


LDY 


ICAUX4,X 


AND HI 


BC41 


202FBD 


JSR 


ISVAR 


GO SET VAR 


BC44 


20A6BC 


JSR 


LDDVX 


GET DEVICE X REG 


BC47 


BD4E03 


LDA 


ICAUX5.X 


GET DATA LENGTH 


BC4A 


4C2DBD 


JMP 


ISVAR1 


GO SET VAR 


XPOINT — Execute POINT 






BC4D 




XPOINT 






BC4D 


209FBC 


JSR 


GIODVC 


GET I/O DEVICE NO 


BC50 


20D5AB 


JSR 


GETPINT 


GET SECTOR NO. 


BC53 


20A6BC 


JSR 


LDDVX 


GET DEVICE X 


BC56 


A5D4 


LDA 


FR0 


SET SECTOR NO. 


BC58 


9D4C03 


STA 


ICAUX3,X 




BC5B 


A5D5 


LDA 


FR0+1 




BC5D 


9D4D03 


STA 


ICAUX4.X 




BC60 


20D5AB 


JSR 


GETPINT 


GET DATA LENGTH 


BC63 


20A6BC 


JSR 


LDDVX 


LOAD DEVICE X 


BC66 


A5D4 


LDA 


FR0 


GET AL 


BC68 


9D4E03 


STA 


ICAUX5.X 


SET DATA LENGTH 


BC6B 


A925 


LDA 


#525 


SET POINT CMD 


BC6D 


85C0 


STA 


IOCMD 




BC6F 


4C22BC 


JMP 


GDI01 


GO DO 


XPUT 


— Execute PUT 






BC72 




XPUT 






BC72 


209FBC 


JSR 


GIODVC 


GET DEVICE # 


BC75 


20E0AB 


JSR 


GET I NT 


GET DATA 


BC78 


A5D4 


LDA 


FR0 


X 


BC7A 


A6C1 


LDX 


IODVC 


LOAD DEVICE # 


BC7C 


4CA1BA 


JMP 


PRCX 


GO PRINT 


XGET 


— Execute GET 






BC7F 




XGET 






BC7F 


209FBC 


JSR 


GIODVC 


GET DEVICE 


BC82 




GET1 






BC82 


A907 


LDA 


#ICGTC 


GET COMMAND 


BC84 


85C0 


STA 


IOCMD 


SET COMMAND 



239 



Source Code 



BC86 


A001 


LDY 


#1 


SET BUFF LENGTH=1 


BC88 


2010BD 


JSR 


103 


DO 10 


BC8B 


20B3BC 


JSR 


IOTEST 


TEST I/O 


BC8E 


A000 


LDY 


#0 


GET CHAR 


BC90 


B1F3 


LDA 


[INBUFF], Y 


X 


BC92 


4C2DBD 


JMP 


ISVAR1 


ASSIGN VAR 


XLOCATE - Execute LOCATE 






BC95 




XLOCATE 






BC95 


2016BA 


JSR 


XPOS 


GET X,Y POSITION 


BC98 


A206 


LDX 


#6 


GET DEVICE # 


BC9A 


20C6BA 


JSR 


GLPX 


X 



BC9D D0E3 "BC82 



GET! 



GIODVC — Get I/O Device Number 



BC9F 

BC9F 2002BD 

BCA2 85C1 

BCA4 P00A "BCB0 



GIODVC 

JSR GIOPRM 

STA IODVC 

BEQ DNERR 



GET PARM 

SET AS DEVICE 

BR IF DVC=0 



LDDVX — Load X Register with I/O Device Offset 



BCA6 



BCA6 


A5C1 


LDA 




IODVC 


GET DEVICE 


BCA8 




ASLA 






MULT BY 16 


BCA8 


+0A 


ASL 




A 




BCA9 




ASLA 








BCA9 


+0A 


ASL 




A 




BCAA 




ASLA 








BCAA 


+0A 


ASL 




A 




BCAB 




ASLA 








BCAB 


+0A 


ASL 




A 




BCAC 


AA 


TAX 






PUT INTO X 


BCAD 


3001 "BCB0 


BMI 




DNERR 


BR DN0>7 


BCAF 


60 


RTS 






AND RETURN 


BCB0 


2018B9 


DNERR 


JSR 


ERRDNO 




IOTEST - Test I/O Status 








BCB3 




IOTEST 








BCB3 


20FBBC 


JSR 




LDIOSTA 


LOAD I/O STATUS 


BCB6 




I0TES2 








BCB6 


3001 "BCB9 


BMI 




SICKIO 


BR IF BAD 


BCB8 


60 


RTS 






ELSE RETURN 


BCB9 




SICKIO 








BCB9 


A000 


LDY 




#0 


RESET DISPLAY FLAG 


BCBB 


8CFE02 


STY 




DSPFLG 




BCBE 


C980 


CMP 




#ICSBRK 


IF BREAK 


BCC0 


D00A "BCCC 


BNE 




:SI01 


SIMULATE ASYNC 


BCC2 


8411 


STY 




BRKBYT 


BREAK 


BCC4 


A5CA 


LDA 




LOADFLG 


IF LOAD FLAG SET 


BCC6 


F003 "BCCB 


BEQ 




:SIOS 




BCC8 


4C00A0 


JMP 




COLDSTART 


DO COLDSTART 


BCCB 




:SI0S 








BCCB 


60 


RTS 








BCCC 


A4C1 


:SI01 


LDY 


IODVC 


PRE-LOAD I/O DEVICE 


BCCE 


C988 


CMP 




#$88 


WAS ERROR EOF 


BCD0 


F00F "BCE1 


BEQ 




:SI04 


BR IF EOF 


BCD2 


85B9 


:SI02 


STA 


ERRNUM 


SET ERROR NUMBER 


BCD4 


C007 


CPY 




#7 


WAS THIS DEVICE #7 


BCD6 


D003 "BCDB 


BNE 




:SI03 


BR IF NOT 


BCD8 


20F1BC 


JSR 




CLSYSD 


CLOSE DEVICE 7 


BCDB 


2072BD 


:SI03 


JSR 


SETDZ 


SET L/D DEVICE = 


BCDE 


4C40B9 


JMP 




ERROR 


REPORT ERROR 



240 



Source Code 



BCEl 


C007 


:SI04 


CPY 


#7 


WAS EOF ON DEVICE 7 


BCE3 


D0ED "BCD2 


BNE 




:SI02 


BR IF NOT 


BCE5 


A25D 


LDX 




#EPCHAR 


WERE WE IN ENTER 


BCE7 


E4C2 


CPX 




PROMPT 




BCE9 


D0E7 *BCD2 


BNE 




:SI02 


BR NOT ENTER 


BCEB 


20F1BC 


JSR 




CLSYSD 


CLOSE DEVICE 7 


BCEE 


4C53A0 


JMP 




SNX2 


GO TO SYNTAX 



CLSYSD — Close System Device 

BCFl CLSYSD 



BCF1 


20A6BC 


CLSYS1 


JSR 


LDDVX 




BCF4 


F00B ~BD01 




BEQ 




NOCD0 


• DON'T CLOSE DEVICE0 


BCF6 


A90C 




LDA 




#ICCLOSE 


■ LOAD CLOSE CORD 


BCF8 


4C26BD 




JMP 




108 


GO CLOSE 


LDIOSTA — Load I/O Status 








BCFB 




LDIOSTA 








BCFB 


20A6BC 




JSR 




LDDVX 


■ GET DEVICE X REG 


BCFE 


BD4303 




LDA 




ICSTA, X 


GET STATUS 


BD01 




NOCD0 








BD01 


60 




RTS 






■ RETURN 


GIOPRM — Get I/O Parameters 






BD02 




GIOPRM 








BD02 


E6A8 




INC 




STINDEX 


SKIP OVER # 


BD04 


20D5AB 


GIOCMD 


JSR 


GETPINT 


GET POSITIVE INT 


BD07 


A5D4 




LDA 




FR0 


MOVE LOW BYTE TO 


BD09 


60 




RTS 








I/O Call Routine 












BD0A 


A0FF 


101 




LDY 


#255 


BUFL » 255 


BD0C 


D002 "BD10 




BNE 




103 




BD0E 


A000 


102 




LDY 


#0 


BUFL = 


BD10 


A900 


103 




LDA 


#0 


BUFL < 256 


BD12 


9D4903 


104 




STA 


ICBLH.X 


SET BUFL 


BD15 


98 




TYA 








BD16 


9D4803 




STA 




ICBLL,X 




BD19 


A5F4 


105 




LDA 


INBUFF+1 


LOAD INBUFF VALUE 


BD1B 


A4F3 




LDY 




INBUFF 




BD1D 
BD20 


9D4503 
98 


106 


TYA 


STA 


ICBAH, X 


SE BUF ADR 


BD21 


9D4403 




STA 




ICBAL.X 




BD24 


A5C0 


107 




LDA 


IOCMD 


LOAD COMMAND 


BD26 


9D4203 


108 




STA 


ICCOM.X 


SET COMMAND 


BD29 


2056E4 




JSR 




CIO 


GO DO I/O 


BD2C 


60 




RTS 






DONE 


ISVAR 


— I/O Variabl 


eSet 










BD2D 




ISVARl 








BD2D 


A000 




LDY 




#0 


GET HIGH ORDER BYTE 


BD2F 




ISVAR 








BD2F 


48 




PHA 






PUSH INT VALUE LOW 


BD30 


98 




TYA 








BD31 


48 




PHA 






PUSH INT VALUE HI 


BD32 


200FAC 




JSR 




P0P1 


GET VARIABLE 


BD35 


68 




PLA 








BD36 


85D5 




STA 




FR0+1 


SET VALUE LOW 


BD38 


68 




PLA 








BD39 


85D4 




STA 




FR0 


SET VALUE HI 


BD3B 


20AAD9 




JSR 




CVIFP 


CONVERT TO FP 


BD3E 


4CI6AC 




JMP 




RTNVAR 


AND RETURN TO TABLE 



241 



Source Code 



CLSALL — CLOSE All lOCBs [except 0] 

BD41 CLSALL 







; TURN OFF 


SOUND 




BD41 


A900 


LDA 




in 




BD43 


A207 


LDX 




#7 




BD45 




:CL 








BD45 


9D00D2 


STA 




SREG3-1.X 




BD48 


CA 


DEX 








BD49 


D0FA "BD45 


BNE 




:CL 




BD4B 


A007 


LDY 




#7 


; START AT DEVICE 7 


BD4D 


84C1 


STY 




IODVC 




BD4F 


20F1BC 


CLALL1 


JSR 


CLSYSD 


; CLOSE DEVICE 


BD52 


C6C1 


DEC 




IODVC 


; DEC DEVICE # 


BD54 


D0F9 "BD4F 


BNE 




CLALL1 


; BR IF NOT ZERO 


BD56 


60 


RTS 








PREADY — Print READY Message 






BD57 




PREADY 








BD57 


A206 


LDX 




tRML-1 


; GET READY MSG LENGTH-1 


BD59 


86F2 


PRDY1 


STX 


CIX 


; SET LEN REM 


BD5B 


BD67BD 


LDA 




RMSG, X 


; GET CHAR 


BD5E 


209FBA 


JSR 




PRCHAR 


; PRINT IT 


BD61 


A6F2 


LDX 




CIX 


; GET LENGTH 


BD63 


CA 


DEX 








BD64 


10F3 "BD59 


BPL 




PRDY1 


; BR IF MORE 


BD66 


60 


RTS 








BD67 


9B59444145 
529B 


RMSG 


DB 


CR, 'YDAER' 


,CR 




= 0007 


RML 


EQU 


*-RMSG 




PRCR 


— Print Carriage Return 








BD6E 


A200 


PRCR 


LDX 


#0 


; SET FOR LAST CHAR 


BD70 


F0E7 ~BD59 


BEQ 




PRDY1 


; AND GO DO IT 



SETDZ — Set Device as LIST/ENTER Device 



BD72 A900 

BD74 85B4 

BD76 85B5 

BD78 60 



SETDZ LDA #0 
STA ENTDTD 
STA LISTDTD 
RTS 



SETSEOL — Set an EOL [Temporarily] after a String EOL 



BD79 




SETSEOL 






BD79 


2098AB 


JSR 


AAPSTR 


; GET STRING WITH ABS ADR 


BD7C 


A5D4 


LDA 


FR0-2+EVSADR 


; PUT IT'S ADR 


BD7E 


85F3 


STA 


INBUFF 


; INTO INBUFF 


BD80 


A5D5 


LDA 


FR0-1+EVSADR 




BD82 


85F4 


STA 


INBUFF+1 




BD84 


A4D6 


LDY 


FR0-2+EVSLEN 


; GET LENGTH LOW 


BD86 


A6D7 


LDX 


FR0-1+EVSLEN 


; IF LEN < 256 


BD88 


F002 "BD8C 


BEQ 


:SSE1 


; THEN BR 


BD8A 


A0FF 


LDY 


»$FF 


; ELSE SET MAX 


BD8C 


BIF3 


:SSE1 LDA 


[INBUFF], Y 


; GET LAST STR CHAR+1 


BD8E 


8597 


STA 


INDEX2 


; SAVE IT 


BD90 


8498 


STY 


INDEX2+1 


; AND IT ' S INDEX 


BD92 


A99B 


LDA 


#CR 


; THEN REPLACE WITH EOL 


BD94 


91F3 


STA 


[INBUFF], Y 




BD96 


8592 


STA 


MEOLFLG 


; INDICATE MODIFIED EOL 


BD98 


60 


RTS 




; DONE 


BD99 




RSTSEOL 




; RESTORE STRING CHAR 


BD99 


A49S 


LDY 


INDEX2+1 


; LOAD INDEX 



242 



Source Code 



BD9B 


A597 


LDA 




INDEX2 


LOAD CHAR 


BD9D 


91F3 


STA 




[INBUFF],Y 


DONE 


BD9F 


A900 


LDA 




#0 




BDA1 


8592 


STA 




MEOLFLG 


RESET EOL FLAG 


BDA3 


60 


RTS 






DONE 


BDA4 


= 0001 


PATCH 


DS 


PATSIZ 





SIN[X]andCOS[X] 



BDA5 


38 




SINERR 


SEC 


TERROR - SET 


BDA6 


60 




RTS 






BDA7 


A904 




SIN 


LDA 


#4 ; 


BDA9 


24D4 




BIT 




FR0 


BDAB 


1006 " 


BDB3 


BPL 




BOTH 


BDAD 


A902 




LDA 




#2 ; 


BDAF 


D002 " 


BDB3 


BNE 




BOTH 


BDB1 


A901 




COS 


LDA 


#1 ; 


BDB3 


85F0 




BOTH 


STA 


SGNFLG 


BDB5 


A5D4 




LDA 




FR0 


BDB7 


297F 




AND 




#S7F 


BDB9 


85D4 




STA 




FR0 


BDBB 


A95F 




LDA 




#PIOV2&$FF 


BDBD 


18 




CLC 






BDBE 


65FB 




ADC 




DEGFLG 


BDC0 


AA 




TAX 






BDC1 


A0BE 




LDY 




#PIOV2/$100 


BDC3 


2098DD 




JSR 




FLD1R 


BDC6 


2028DB 




JSR 




FDIV ; 


BDC9 


9001 " 


BDCC 


BCC 




SINF7 


BDCB 


60 




S I NOVF 


RTS 




BDCC 






SINF7 






BDCC 


A5D4 




LDA 




FR0 


BDCE 


297F 




AND 




#$7F f 


BDD0 


38 




SEC 






BDD1 


E940 




SBC 




#$40 


BDD3 


302B " 


BE00 


BMI 




SINF3 ; 


BDD5 


C904 




SINF6 


CMP 


#FPREC-2 


BDD7 


10CC " 


BDA5 


BPL 




SINERR ; 


BDD9 


AA 




TAX 






BDDA 


B5D5 




LDA 




FR0+1.X ; 


BDDC 


85F1 




STA 




XFMFLG 


BDDE 


2910 




AND 




#510 7 


BDE0 


F002 * 


BDE4 


BEQ 




SINF5 


BDE2 


A902 




LDA 




#2 ; 


BDE4 


18 




SINF5 


CLC 




BDE5 


65F1 




ADC 




XFMFLG 


BDE7 


2903 




AND 




#3 


BDE9 


65F0 




ADC 




SGNFLG ; 


BDEB 


85F0 




STA 




SGNFLG 


BDED 


86F1 




STX 




XFMFLG ; 


BDEF 


20B6DD 




JSR 




FMOVE 


BDF2 


A6F1 




LDX 




XFMFLG 


BDF4 


A900 




LDA 




#0 


BDF6 


95E2 




SINF1 


STA 


FR1+2.X ; 


BDF8 


E8 




I NX 






BDF9 


E003 




CPX 




#FPREC-3 


BDFB 


90F9 * 


BDF6 


BCC 




SINF1 


BDFD 


2060DA 




JSR 




FSUB 


BE00 


46F0 




SINF3 


LSR 


SGNFLG ; 


BE02 


900D " 


BE11 


BCC 




SINF4 ; 


BE04 


20B6DD 




JSR 




FMOVE ; 


BE07 


A271 




LDX 




#FPONE&$FF 


BE09 


A0BE 




LDY 




#FPONE/$100 


BE0B 


2089DD 




JSR 




FLD0R 


BE0E 


2060DA 




JSR 




FSUB 


BE11 






SINF4 






BE11 


A2E6 




LDX 




#FPSCR&$FF 


BE13 


A005 




LDY 




#FPSCR/$100 



FLAG SIN[X] ENTRY RIGHT NOW 

SIN[-X] 
FLAG COS[X] ENTRY 
FORCE POSITIVE 



X/CPI/2] OR X/90 
OVERFLOW 

CHECK EXPONENT 

QUADRANT - USE AS IS 
FIND QUAD NO & REMAINDER 
OUT OF RANGE 
X->LSB OR FR0 
LSB 

CHECK 10 'S DIGIT 

ODD - ADD 2 TO QUAD # 



QUADRANT = 0,1,2,3 
ADJUST FOR SINE VS COSINE 



SAVE DEC PT LOC 
COPY TO FR1 



CLEAR FRACTION 



LEAVE REMAINDER 

WAS QUAD ODD 

NO 

YES - USE 1.0 - REMAINDER 



NOW DO THE SERIES THING 
SAVE ARG 



243 



Source Code 



BE15 
BE18 
BE1B 
BE1E 
BE 20 
BE22 
BE 24 
BE26 
BE29 
BE2B 
BE2D 
BE30 
BE33 
BE35 
BE37 
BE38 
BE3A 
BE3C 
BE3E 
BE40 
BE41 

BE47 

BE4D 

BE53 

BE59 

BE5F 



BE65 
BE6B 
BE71 



20A7DD 

20B6DD 

20DBDA 

B085 "BDA5 

A906 

A241 

A0BE 

2040DD 

A2E6 

A005 

2098DD 

20DBDA 

46F0 

9009 "BE40 

18 

A5D4 

F004 ~BE40 

4980 

85D4 

60 

BD03551499 

39 

3E01604427 

52 

BE46817543 

55 

3F07969262 

39 

BF64596408 

67 

4001570796 

32 

= 0006 

4090000000 

00 

3F01745329 

25 

4001000000 

00 



JSR 
JSR 
JSR 
BCS 
LDA 
LDX 
LDY 
JSR 
LDX 
LDY 
JSR 
JSR 
LSR 
BCC 
CLC 
LDA 
BEQ 
EOR 
STA 
SINDON RTS 



FST0R 

FMOVE 

FMUL 

SINERR 

#NSCF 

#SCOEF&$FF 

#SCOEF/$100 

PLYEVL 

#FPSCRS,$FF 

#FPSCR/$100 

FLD1R 

FMUL 

SGNFLG 

SINDON 

FR0 

SINDON 
#$80 
FR0 



;X->FR1 
;X**2->FR0 



EVALUATE P[X**2] 



X-> FR1 

SIN[X] = X*P[X**2] 

WAS QUAD 2 OR 3? 

NO - THRU 

YES 

FLIP SIGN 

[UNLESS ZERO] 



; RETURN 



SCOEF .BYTE $BD, $03 , $55 , $14 , $99, $39 ; -.00000354149939 
.BYTE S3E, $01, $60, $44, $27, $52 ; 0.000160442752 
.BYTE $BE, $46, $81, $75, $43, $55 ; -.004681754355 
.BYTE $3F, $07, $96, $92, $62, $39 ; 0.0796926239 
.BYTE $BF, $64, $59, $64, $08, $67 ; -.6459640867 

PIOV2 .BYTE $40, $01, $57, $07, $96, $32 ;Pl/2 

NSCF EQU (*-SCOEF)/FPREC 

.BYTE $40, $90, 0,0, 0,0 ; 90 DEG 

PIOV18 .BYTE $3F, $01, $74, $53, $29, $25 ;Pl/180 

FPONE .BYTE $40,1,0,0,0,0 ; 1.0 



ATAN[X] — Arctangent 



BE77 
BE79 
BE7B 
BE7D 
BE7F 
BE81 
BE83 
BE85 
BE87 
BE89 
BE8B 
BE8D 
BE8F 
BE91 
BE93 
BE95 
BE97 
BE 9 A 
BE 9 A 

BE9C 
BE9E 
BEA1 
BE A 4 
BEA7 
BEA9 
BEAB 



A900 

85F0 

85F1 

A5D4 

297F 

C940 

3015 "BE9A 

A5D4 

2980 

85F0 

E6F1 

A97F 

25D4 

85D4 

A2EA 

A0DF 

2095DE 

A2E6 

A005 

20A7DD 

20B6DD 

20DBDA 

B039 "BEE2 

A90B 

A2AE 



BEAD A0DF 



ATAN 

STA 
STA 
LDA 
AND 
CMP 
BMI 
LDA 
AND 
STA 
INC 
LDA 
AND 
STA 
LDX 
LDY 
JSR 

ATAN1 

LDX 

LDY 
JSR 
JSR 
JSR 
BCS 
LDA 
LDX 
LDY 



#0 
SGNFLG 
XFMFLG 
FR0 
#$7F 
#$40 
ATAN1 
FR0 
#$80 
SGNFLG 
XFMFLG 
#$7F 
FR0 
FR0 

#FP9S&$FF 
#FP9S/$100 
XFORM 

#FPSCR&$FF 

#FPSCR/$100 

FST0R 

FMOVE 

FMUL 

ATNOUT 

#NATCF 

#ATCOEF&$FF 

#ATCOEF/$100 



ARCTAN[X] 

SIGN FLAG OFF 

5. TRANSFORM FLAG 



CHECK X VS 1.0 

X<1.0 - USE SERIES DIRECTLY 

X> = 1.0 - SAVE SIGN S. TRANSFORM 



REMEMBER SIGN 



FORCE PLUS 



; CHANGE ARG TO [X-1]/[X+1] 

; ARCTAN[X], -1<X<1 BY SERIES 
; OF APPROXIMATIONS 

;X->FSCR 
; X->FR1 
; X*X->FR0 
; ' FLOW 



244 



Source Code 






BEAF 


2040DD 


JSR 


PLYEVL 


P[X*X] 


BEB2 


B02E "BEE2 


BCS 


ATNOUT 




BEB4 


A2E6 


LDX 


#FPSCRS,?FF 




BEB6 


A005 


LDY 


#FPSCR/?100 




BEB8 


2098DD 


JSR 


FLD1R 


X->FR1 


BEBB 


20DBDA 


JSR 


FMUL 


X*P[X*X] 


BEBE 


B022 "BEE2 


BCS 


ATNOUT 


' FLOW 


BEC0 


A5F1 


LDA 


XFMFLG 


WAS ARG XFORM'D 


BEC2 


F010 "BED4 


BEQ 


ATAN2 


NO 


BEC4 


A2F0 


LDX 


#PIOV4&5FF 


YES-ADD ARCTAN [1.0] 


BEC6 


A0DF 


LDY 


#PIOV4/5100 




BEC8 


2098DD 


JSR 


FLD1R 




BECB 


2066DA 


JSR 


FADD 




BECE 


A5F0 


LDA 


SGNFLG 


GET ORG SIGN 


BED0 


05D4 


ORA 


FR0 




BED2 


85D4 


STA 


FR0 


ATAN[-X] = - ATAN[X] 


BED4 


A5FB 


ATAN2 LDA 


DEGFLG 


RADIANS OR DEGREES 


BED6 


F00A ~BEE2 


BEQ 


ATNOUT 


RAD - FINI 


BED8 


A26B 


LDX 


#PIOV18i$FF 


DEG - DIVIDE BY PI/1 


BEDA 


A0BE 


LDY 


*PIOV18/$100 




BEDC 


2098DD 


JSR 


FLD1R 




BEDF 


2028DB 


JSR 


FDIV 




BEE 2 


60 


ATNOUT RTS 







PI/4 



SQR[X] — Square Root 



BEE 3 


38 


BEE 4 


60 


BEE 5 


A900 


BEE 7 


85F1 


BEE9 


A5D4 


BEEB 


30F6 " 


BEED 


C93F 


BEEF 


F017 * 


BEF1 


18 


BEF2 


6901 


BEF4 


85F1 


BEF6 


85E0 


BEF8 


A901 


BEFA 


85E1 


BEFC 


A204 


BEFE 


A900 


BF00 


95E2 


BF02 


CA 


BF03 


10FB " 


BF05 


2028DB 


BF08 




BF08 


A906 


BF0A 


85EF 


BF0C 


A2E6 


BF0E 


A005 


BF10 


20A7DD 


BF13 


20B6DD 


BF16 


A293 


BF18 


A0BF 


BF1A 


2089DD 


BF1D 


2060DA 


BF20 


A2E6 


BF22 


A005 


BF24 


2098DD 


BF27 


20DBDA 


BF2A 


A2EC 


BF2C 


A005 


BF2E 


20A7DD 


BF31 


20B6DD 


BF34 


A2E6 


BF36 


A005 


BF38 


2089DD 



SQRERR 


SEC 




;SET FAIL 


RTS 








SQR 


LDA 


#0 




STA 




XFMFLG 




LDA 




FR0 




BMI 




SQRERR 




CMP 




#$3F 




BEQ 




FSQR 


; X IN RANGE OF APPROX 


CLC 








ADC 




#1 




STA 




XFMFLG 


,- NOT IN RANGE - TRANS 


STA 




FR1 


; MANTISSA = 1 


LDA 




#1 




STA 




FR1 + 1 




LDX 




#FPREC-2 




LDA 




#0 




SQR1 


STA 


FR1+2.X 




DEX 








BPL 




SQR1 




JSR 




FDIV 


; X/100**N 


FSQR 






;SQR[X], 0.1<=X<1.0 


LDA 




#6 




STA 




SQRCNT 




LDX 




#FSCRS.$FF 




LDY 




#FSCR/$100 




JSR 




FST0R 


; STASH X IN FSCR 


JSR 




FMOVE 


;X->FR1 


LDX 




#FTWOS,$FF 




LDY 




#FTWO/?100 




JSR 




FLD0R 


,-2.0->FR0 


JSR 




FSUB 


; 2 . 0-X 


LDX 




#FSCRi$FF 




LDY 




#FSCR/$100 




JSR 




FLD1R 


;X->FR1 


JSR 




FMUL 


;X*[2.0-X] :1ST APPROX 


SQRLP 


LDX 


#FSCR16,$FF 




LDY 




#FSCR1/?100 




JSR 




FST0R 


;Y->FSCR1 


JSR 




FMOVE 


;Y->FR1 


LDX 




#FSCR6,$FF 




LDY 




#FSCR/$100 




JSR 




FLD0R 





245 



Source Code 



BF3B 
BF3E 
BF40 
BF42 
BF45 
BF48 
BF4A 
BF4C 
BF4F 
BF52 
BF54 
BF56 
BF58 
BF5A 
BF5D 
BF60 
BF62 
BF64 
BF66 
BF68 

BF6B 
BF6D 
BF6F 
BF70 
BF72 
BF73 
BF73 
BF74 
BF75 
BF77 
BF79 
BF7B 
BF7D 
BF7D 
BF7E 
BF80 
BF82 
BF84 
BF86 
BF88 
BF8A 
BF8C 
BF8D 
BF8F 

BF92 
BF93 



2028DB 

A2EC 

A005 

2098DD 

2060DA 

A26C 

A0DF 

2098DD 

20DBDA 

A5D4 

F00E "BF64 

A2EC 

A005 

2098DD 

2066DA 

C6EF 

10C6 "BF2A 

A2EC 

A005 

2089DD 

A5F1 

F023 "BF92 

38 

E940 

18 



+6A 
18 

6940 
297F 
85E0 
A5F1 

+6A 
A901 
9002 
A910 
85E1 
A204 
A900 
95E2 
CA 
10FB 



BF84 



20DBDA 

60 

4002000000 

00 



JSR 

LDX 

LDY 

JSR 

JSR 

LDX 

LDY 

JSR 

JSR 

LDA 

BEQ 

LDX 

LDY 

JSR 

JSR 

DEC 

BPL 
SQRDON LDX 

LDY 

JSR 
; WAS 

LDA 

BEQ 

SEC 

SBC 

CLC 

RORA 

ROR 

CLC 

ADC 

AND 

STA 

LDA 

RORA 

ROR 

LDA 

BCC 

LDA 
SQR2 STA 

LDX 

LDA 
SQR3 STA 

DEX 

BPL 

JSR 



FDIV 

#FSCR1&?FF 

#FSCR1/$100 

FLD1R 

FSUB 

#FHALF&$FF 

#FHALF/$100 

FLD1R 

FMUL 

FR0 

SQRDON 

#FSCR1&$FF 

#FSCR1/$100 

FLD1R 

FADD 

SQRCNT 

SQRLP 

#FSCR1&$FF 
#FSCR1/$100 
FLD0R 

ARG TRANSFORMED 
XFMFLG 
SQROUT 

#$40 



#?40 
#$7F 
FR1 
XFMFLG 

A 

#1 

SQR2 

#$10 

FR1 + 1 
#FPREC-2 
#0 

FR1+2.X 

SQR3 

FMUL 



;X/Y 



;[X/Y]-Y 



;0.5*[[X/Y]-Y]=DELTAY 
; DELTA 0.0 



;Y=Y+DELTA Y 
; COUNT & LOOP 



I DELTA = - GET Y BACK 



YES - TRANSFORM RESULT 
DIVIDE EXP BY 2 



MANTISSA = 1 

WAS EXP ODD OR EVEN 

ODD - MANT =10 



SQROUT 
FTWO 



RTS 
.BYTE 



$40,2, 



; CLEAR REST OF MANTISSA 

; SQR[X] = SQR[X/100**N] 
* [10**N] 

,0 ; 2.0 



BF99 
D800 



Floating Point 



ORG 
LOCAL 



ASCIN — Convert ASCII Input to Internal Form 



INBUFF - POINTS TO BUFFER WITH ASCII 
CIX - INDEX TO 1ST BYTE OF # 



CC SET - CARRY SET IF NOT t 
CARRY CLEAR OF t 



D800 




AFP 




D800 




CVAFP 




D800 




ASCIN 




D800 


20A1DB 


JSR 


SKPBLANK 


D803 


20BBDB 


JSR 


:TSTCHAR 


D806 


B039 "0841 


BCS 


:NONUM 



SEE IF THIS COULD BE A NUMBER 
BR IF NOT A NUMBER 



246 



Source Code 









SET 


INITI 


D808 


A2ED 


LDX 




#EEXP 


D80A 


A004 


LDY 




#4 


D80C 


2048DA 


JSR 




ZXLY 


D80F 


A2FF 


LDX 




#$FF 


D811 


86F1 


STX 




DIGRT 



D813 2044DA 
D816 F004 "D81C 



ZERO 4 VALUES 

X 

X 

SET TO SFF 

CLEAR FR0 

UNCONDITIONAL BR 



D818 



D818 


A9FF 




LDA 


#$FF 


D81A 


85F0 




STA 


FCHRFLG 


D81C 






: IN2 




D81C 


2094DB 




JSR 


:GETCHAR 


D81F 


B021 " 


D842 


BCS 


:NONl 



IT'S A NUMBER 



D821 


48 


PHA 




D822 


A6D5 


LDX 


FR0M 


D824 


D011 ~D837 


BNE 


:INCE 


D826 


20EBDB 


JSR 


NIBSH0 



SET 1ST CHAR FLAG TO NON 

ZERO 

X 



GET INPUT CHAR 

BR IF CHAR NOT NUMBER 



SAVE ON CPU STACK 
GET 1ST BYTE 
INCR EXPONENT 

SHIFT FR0 ONE NIBBLE LEFT 



D829 68 
D82A 05D9 
D82C 85D9 



D82E A6F1 

D830 30E6 *D818 

D832 E8 

D833 86F1 

D835 D0E1 "D818 



PLA 

ORA FR0M+FMPREC-1 

STA FR0M+FMPREC-1 



GET DIGIT ON CPU STACK 
OR INTO LAST BYTE 
SAVE AS LAST BYTE 



COUNT CHARACTERS AFTER DECIMAL POINT 



LDX 
BMI 
I NX 
STX 
BNE 



DIGRT 
:IN1 



DIGRT 
:IN1 



GET # OF DIGITS RIGHT 

IF = $FF, NO DECIMAL POINT 

ADD IN THIS CHAR 

SAVE 

GET NEXT CHAR 



INCREMENT # OR DIGIT MORE THAN 9 



D837 




:INCE 




D837 


68 


PLA 




D838 


A6F1 


LDX 


DIGRT 


D83A 


1002 "D83E 


BPL 


:INCE2 


D83C 


E6ED 


INC 


EEXP 


D83E 




:INCE2 




D83E 


4C18D8 


JMP 


: INI 


D841 




:NONUM 




D841 


60 


RTS 





CLEAR CPU STACK 

HAVE DP? 

IF YES, DON'T INCR E COUNT 

INCR EXPONENT 

GET NEXT CHAR 



RETURN FAIL 



NON-NUMERIC IN NUMBER BODY 



D842 






:NONl 




D842 


C92E 




CMP 


#' -' 


D844 


F014 


"D85A 


BEQ 


:DP 


D846 


C945 




CMP 


#'E' 


D848 


F019 


"D863 


BEQ 


:EXP 


D84A 


A6F0 




LDX 


FCHRFLG 


D84C 


D068 


"D8B6 


BNE 


:EXIT 


D84E 


C92B 




CMP 


# '+' 



IS IT DECIMAL POINT? 
IF YES, PROCESS IT 
IS IT E FOR EXPONENT? 
IF YES, DO EXPONENT 

IS THIS THE 1ST CHAR 

IF NOT, END OF NUMERIC INPUT 

IS IT PLUS? 



247 



Source Code 



D850 


F0C6 


~D818 


BEQ 


:IN1 


D852 


C92D 




CMP 


#'-' 


D854 


F000 


~D856 


BEQ 


: MINUS 


D856 






:MINUS 




D856 


85EE 




STA 


NSIGN 


D858 


F0BE 


"D818 


BEQ 


: INI 


D85A 






:DP 




D85A 


A6F1 




LDX 


DIGRT 


D85C 


1058 


"D8B6 


BPL 


:EXIT 


D85E 


E8 




I NX 




D85F 


86F1 




STX 


DIGRT 


D861 


F0B5 


~D818 


BEQ 


:IN1 


D863 






:EXP 




D863 


A5F2 




LDA 


CIX 


D865 


85EC 




STA 


FRX 


D867 


2094DB 


JSR 


:GETCHAR 


D86A 


B037 


"D8A3 


BCS 


:N0N2 



GO FOR NEXT CHAR 
IS IT MINUS? 



SAVE SIGN FOR LATER 
UNCONDITIONAL BRANCH FOR 
NEXT CHAR 



IS DIGRT STILL = FF? 

IF NOT, ALREADY HAVE DP 

INCR TO ZERO 

SAVE 

UNCONDITIONAL BR FOR NEXT 

CHAR 



GET INDEX 

SAVE 

GET NEXT CHAR 

BR IF NOT NUMBER 



D86C 




D86C 


AA 


D86D 


A5ED 


D86F 


48 


D870 


86ED 


D872 


2094DB 


D875 


B017 * 


D877 


48 


D878 


A5ED 


D87A 




D87A 


+0A 


D87B 


85ED 


D87D 




D87D 


+0A 


D87E 




D87E 


+0A 


D87F 


65ED 


D881 


85ED 


D883 


68 


D884 


18 


D885 


65ED 


D887 


85ED 


D889 


A4F2 


D88B 


209DDB 


D88E 




D88E 


A5EF 


D890 


F009 " 


D892 


A5ED 


D894 


49FF 


D896 


18 


D897 


6901 


D899 


85ED 


D89B 




D89B 


68 


D89C 


18 


D89D 


65ED 


D89F 


85ED 


D8A1 


D013 " 



IT'S A NUMBER IN AN EXPONENT 



EXP 2 
TAX 
LDA 
PHA 
STX 
JSR 



BCS 
PHA 

LDA 

AS LA 

ASL 

STA 

ASLA 

ASL 

ASLA 

ASL 

ADC 

STA 

PLA 

CLC 

ADC 

STA 

LDY 
JSR 



EEXP 
:GETCHAR 



A 
EEXP 



A 

EEXP 

EEXP 



EEXP 
EEXP 



CIX 

:GCHR1 



3 




LDA 


ESIGN 


BEQ 
LDA 


:EXP1 
EEXP 


EOR 
CLC 


#SFF 


ADC 
STA 

1 


#1 
EEXP 


PLA 




CLC 
ADC 


EEXP 


STA 


EEXP 


BNE 


:EXIT 



SAVE 1ST CHAR OF EXPONENT 
GET # OF CHAR OVER 9 
SAVE IT 

SAVE 1ST CHAR OF EXPONENT 
GET NEXT CHAR 



IF NOT # NO SECOND DIGIT 
SAVE SECOND DIGIT 



GET 1ST DIGIT 
GET DIGIT * 10 



X 

SAVE 

GET SECOND DIGIT 

GET EXPONENT INPUTTED 
SAVE 

INC TO NEXT CHAR 
X 



GET SIGN OF EXPONENT 

IF NO SIGN, IT IS + 

GET EXPONENT ENTERED 

COMPLEMENT TO MAKE MINUS 

X 

X 

SAVE 

GET # DIGITS MORE THAN 9 
CLEAR CARRY 

ADD IN ENTERED EXPONENT 
SAVE EXPONENT 
UNCONDITIONAL BR 



248 



Source Code 



NON-NUMERIC IN EXPONENT 



D8A3 






NON2 


D8A3 


C92B 




CMP 


D8A5 


F006 


"D8AD 


BEQ 


D8A7 


C92D 




CMP 


D8A9 


D007 


"D8B2 


BNE 


D8AB 






EMIN 


D8AB 


85EF 




STA 


D8AD 






EPLUS 


D8AD 


2094DB 


JSR 


D8B0 


90BA 


"D86C 


BCC 



: EPLUS 
:NOTE 



:GETCHAR 
:EXP2 



IS IT PLUS? 
IF YES BR 
IS IT A MINUS? 
IF NOT, BR 



; SAVE EXPONENT SIGN 



E NOT PART OF OUR # 



D8B2 




:NOTE 




D8B2 


A5EC 


LDA 


FRX 


D8B4 


85F2 


STA 


CIX 



GET CHARACTER 

IF A #, GO PROCESS EXPONENT 



POINT TO 1 PAST E 
RESTORE CIX 



D8B6 



D8B6 C6F2 



FALL THRU TO EXIT 

WHOLE # HAS BEEN INPUTTED 
EXIT 

BACK UP ONE CHAR 
DEC CIX 



; DECREMENT INDEX 



D8B8 


A5ED 




LDA 


EEXP 


D8BA 


A6F1 




LDX 


DIGRT 


D8BC 


3005 


~D8C3 


BMI 


:EXIT1 


D8BE 


F003 


"D8C3 


BEQ 


:EXITI 


D8C0 


38 




SEC 




D8C1 


E5F1 




SBC 


DIGRT 



D8C3 




:EXIT1 




D8C3 


48 


PHA 




D8C4 




ROLA 




D8C4 


+2A 


ROL 


A 


D8C5 


68 


PLA 




D8C6 




RORA 




D8C6 


+6A 


ROR 


A 


D8C7 


85ED 


STA 


EEXP 


D8C9 


9003 "D8CE 


BCC 


:EVEN 


D8CB 


20EBDB 


JSR 


NIBSH0 


D8CE 




:EVEN 




D8CE 


A5ED 


LDA 


EEXP 


D8D0 


18 


CLC 




D8DI 


6944 


ADC 


#$44 


D8D3 


85D4 


STA 


FR0 


D8D5 


2000DC 


JSR 


NORM 


D8D8 


B00B ~D8E5 


BCS 


: IND2 



CALCULATE POWER OF 10 = EXP - DIGITS RIGHT 
WHERE EXP = ENTERED EXPONENT [COMPLEMENT OF -] 
+ # DIGITS MORE THAN 9 



GET EXPONENT 

GET # DIGITS RIGHT OF DECIMAL 

NO DECIMAL POINT 

# OF DIGITS AFTER D.P.=0 

GET EXP - DIGITS RIGHT 

X 



SHIFT RIGHT ALGEBRAIC TO DIVIDE BY 2 = POWER OF 100 



; SET CARRY WITH SIGN OF 
EXPONENT 

; GET EXPONENT AGAIN 

; SHIFT RIGHT 

; SAVE POWER OF 100 

r IF NO CARRY # EVEN 

; ELSE SHIFT 1 NIBBLE LEFT 

; ADD 40 FOR EXCESS 64+4 

FOR NORM 

; X 

,- X 

; SAVE AS EXPONENT 

; NORMALIZE NUMBER 

; IF CARRY SET, IT'S AN ERROR 



249 



Source Code 



SET MANTISSA SIGH 



D8DA 


A6EE 




LDX 


NSIGN 


; IS SIGN OP # MINUS? 


D8DC 


F006 


"D8E4 


BEQ 


: INDON 


r IP NOT, BR 


D8DE 


A5D4 




LDA 


PR0 


; GET EXPONENT 


D8E0 


0980 




ORA 


#?80 


; TURN ON MINUS # BIT 


D8E2 


85D4 




STA 


FR0 


; SET IN FR0 EXP 


D8E4 






:INDON 






D8E4 


18 




CLC 




; CLEAR CARRY 


D8E5 






:IND2 






D8E5 


60 




RTS 







FPASC — Convert Floating Point to ASCII 

* ON ENTRY 



FR0 - | TO CONVERT 







* 
* 
* 


ON 


EXIT 


D8E6 




* 
CVFASC 






D8E6 




FASC 






D8E6 


2051DA 


JSR 




INTLBF 


D8E9 


A930 


LDA 




t'0 1 


D8EB 


8D7F05 


STA 




LBUFF-1 



INBUFF - POINTS TO START OF # 
HIGH ORDER BIT OF LAST BYTE IS ON 



;SET INBUFF TO PT TO LBUFF 



GET ASCII ZERO 

PUT IN FRONT OF LBUFF 



TEST FOR E FORMAT REQUIRED 



D8EE 


A5D4 


D8F0 


F028 


D8F2 


297F 


D8F4 


C93F 


D8F6 


9028 


D8F8 


C945 


D8FA 


B024 


D8FC 


38 


D8FD 


E93F 



D8FF 2070DC 



D902 


20A4DC 


D905 


0980 


D907 


9D8005 


D90A 


AD8005 


D90D 


C92E 


D90F 


F003 *D914 


D911 


4C88D9 


D914 




D914 


20C1DC 


D917 


4C9CD9 



LDA 


PR0 


BEQ 


:EXP0 


AND 


#$7F 


CMP 


#$3F 


BCC 


:EFORM 


CMP 


#$45 


BCS 


:EFORM 



PROCESS NOT E FORMAT 



SEC 




SBC 


#$3F 


JSR 


:CVFR0 


JSR 


:FNZERO 


ORA 


#?80 


STA 


LBUFF, X 


LDA 


LBUFF 


CMP 


#' -' 


BEQ 


:FN6 


JMP 


:FN5 


JSR 


:DECINB 


JMP 


:FN4 



GET EXPONENT 

IF EXP = 0, # = 0, SO BR 

AND OUT SIGN 

IS IT LESS THAN 3F 

IF YES, E FORMAT REQUIRED 

IF IT IS > 44 

IF YES, E FORMAT REQUIRED 



SET CARRY 

GET DECIMAL POSITION 

CONVERT FR0 TO ASCII CHAR 

FIND LAST NON-ZERO CHARACTER 
TURN ON HIGH ORDER BIT 
STORE IT BACK IN BUFFER 

GET 1ST CHAR IN LBUFF 
IS IT DECIMAL? 
BR IF YES 
ELSE JUMP 

DECIMAL INBUFF 

DO FINAL ADJUSTMENT 



EXPONENT IS ZERO - # IS ZERO 



D91A 

D91A A9B0 

D91C 8D8005 

D91F 60 



:EXP0 

LDA 
STA 
RTS 



#?80+$3£ 
LBUFF 



GET ASCII WITH MSB 
PUT IN BUFFER 



PROCESS E FORMAT 








:EFORM 







A901 


LDA 


#1 


2 


2070DC 


JSR 


:CVFR0 



GET DECIMAL POSITION 
CONVERT FR0 TO ASCII 
LBUFF 



250 



Source Code 



D92 5 


20A4DC 


JSR 


:FNZERO 


D928 


E8 


I NX 




D929 


86P2 


STX 


CIX 






ADJUST EXPO 


D92B 


A5D4 


LDA 


FR0 


D92D 




ASLA 




D92D 


+0A 


ASL 


A 


D92E 


38 


SEC 




D92F 


E980 


SBC 


#S40*2 


D931 


AE8005 


LDX 


LBUFF 


D934 


E030 


CPX 


#'0' 


D936 


P017 ~D94F 


BEQ 


:EF1 






PUT 


DECIMAL 



D938 AE8105 

D93B AC8205 

D93E 8E8205 

D941 8C8105 



GET RID OF TRAILING ZEROS 

I NCR INDEX 

SAVE INDEX TO LAST CHAR 



GET EXPONENT 

MULT BY 2 [GET RID OF 

SIGN TOO] 



SUB EXCESS 64 



GET 1ST CHAR IN LBUFF 
IS IT ASCII 0? 



PUT DECIMAL AFTER 1ST CHAR [IT'S AFTER 2ND NOW] 



LDX LBUFF+1 

LDY LBUFF+2 

STX LBUFF+2 

STY LBUFF+1 



SWITCH D.P. + 2ND DIGIT 

X 

X 

X 



D944 A6F2 

D946 E002 

D948 D002 "D94C 

D94A E6F2 



D94C 




D94C 


18 


D94D 


6901 


D94F 




D94F 


85ED 


D951 


A945 


D953 


A4F2 


D955 


209FDC 


D958 


84F2 



LDX 


CIX 


CPX 


#2 


BNE 


: NOINC 


INC 


CIX 


NOINC 




CLC 




ADC 


#1 



CONVERT EXP TO ASCII 



STA EEXP 

LDA # ' E ' 

LDY CIX 

JSR rSTCHAR 

STY CIX 



IF CIX POINTS TO D.P. 

THEN INC 

X 

X 



X 
X 



SAVE EXPONENT 
GET ASCII E 
GET POINTER 
STORE CHARACTER 
SAVE INDEX 



D95A A5ED 

D95C 100B "D969 



D95E A900 



LDA 
BPL 



EEXP 
:EPL 



; GET EXPONENT 
; BR IF PLUS 



D960 


38 


D961 


E5ED 


D963 


85ED 


D965 


A92D 


D967 


D002 "D96B 


D969 




D969 


A92B 


D96B 




D96B 


209FDC 


D96E 


A200 


D970 


A5ED 


D972 




D972 


38 


D973 


E90A 



EXPONENT IS MINUS - COMPLEMENT IT 



SEC 
SBC 
STA 

LDA 

BNE 



:EF2 



LDX 
LDA 



SEC 
SBC 



#0 



EEXP 
EEXP 



:EF2 



:STCHAR 



#0 
EEXP 



#10 



; SUBTRACT FROM TO 

COMPLEMENT 
; X 
; X 



GET A MINUS 



GET A PLUS 

STORE A CHARACTER 



SET COUNTER FOR # OF TENS 
GET EXPONENT 



; SUBTRACT 10 



251 



Source Code 



D975 


9003 * 


D97A 


BCC 


:EF4 


D977 


E8 




I NX 




D978 


D0F8 * 


D972 


BNB 


:EF3 


D97A 






:EF4 




D97A 


18 




CLC 




D97B 


690A 




ADC 


#10 


D97D 


48 




PHA 




D97E 


8A 




TXA 




D97F 


209DDC 




JSR 


:STNUM 


D982 


68 




PLA 




D983 


0980 




ORA 


#$80 


D985 


209DDC 




JSR 


:STNUM 



IF < 0, BRANCH 
INCR # OF 10' S 
BR UNCONDITIONAL 



ADD BACK IN 10 

X 

SAVE 

GET # OF 10' S 

PUT 10 'S IN EXP IN BUFFER 

GET REMAINDER 

TURN ON HIGH ORDER BIT 

PUT IN BUFFER 



FINAL ADJUSTMENT 



D988 




D988 


AD8005 


D98B 


C930 


D98D 


D00D "D99C 


D98F 


18 


D990 


A5F3 


D992 


6901 


D994 


85F3 


D996 


A5F4 


D998 


6900 


D99A 


85F4 


D99C 




D99C 


A5D4 


D99E 


1009 "D9A9 


D9A0 


20C1DC 


D9A3 


A000 


D9A5 


A92D 


D9A7 


91F3 


D9A9 




D9A9 


60 



LDA 


LBUFF 


CMP 


#'0' 


BNE 


:FN4 




INCREMENT INBU 


CLC 




LDA 


INBUFF 


ADC 


#1 


STA 


INBUFF 


LDA 


INBUFF+1 


ADC 


#0 


STA 


INBUFF+1 


:FN4 




LDA 


FR0 


BPL 


: FADONE 


JSR 


rDECINB 


LDY 


#0 


LDA 


#'-' 


STA 


[INBUFF], Y 


: FADONE 




RTS 





GET 1ST BYTE IN LBUFF 

[OUTPUT] 

IS IT ASCII 0? 

IF NOT BR 



ADD 1 TO INBUFF 

X 

X 

X 

X 

X 

X 

GET EXPONENT OF # 

IF SIGN +, WE ARE DONE 

DECR INBUFF 
GET INDEX 
GET ASCII - 
SAVE - IN BUFFER 



IFP — Convert Integer to Floating Point 



ON ENTRY 
ON EXIT 



FR0 - CONTAINS INTEGER 

FR0 - CONTAINS FLOATING POINT # 



D9AA 




D9AA 




D9AA 


A5D4 


D9AC 


85F8 


D9AE 


A5D5 


D9B0 


85F7 


D9B2 


2044DA 


D9B5 


F8 


D9B6 


A010 


D9B8 




D9B8 


06F8 


D9BA 


26F7 



CVIFP 
IFP 



MOVE INTEGER AND REVERSE BYTES 



LDA 
STA 
LDA 
STA 

JSR 
SED 



FR0 

ZTEMP4+1 
FR0+1 
ZTEMP4 

ZFR0 



DO THE CONVERT 



LDY 
:IFP1 

ASL 
ROL 



116 



ZTEMP4+1 
ZTEMP4 



GET INTEGER LOW 
SAVE AS INTEGER HIGH 
GET INTEGER HIGH 
SAVE AS INTEGER LOW 

CLEAR FR0 

SET DECIMAL MODE 



; GET # BITS IN INTEGER 



SHIFT LEFT INTEGER LOW 
SHIFT LEFT INTEGER HIGH 



252 



Source Code 



D9BC A203 
D9BE 



D9BE B5D4 

D9C0 75D4 

D9C2 95D4 

D9C4 CA 

D9C5 D0F7 "D9BE 

D9C7 88 

D9C8 D0EE "D9B8 

D9CA D8 



D9CB A942 
D9CD 85D4 
D9CF 4C00DC 



LDX 
:IFP2 



CARRY NOW SET IF THERE WAS A 
BIT 

BIGGEST INTEGER IS 3 BYTES 



DOUBLE # AND ADD IN 1 IF CARRY SET 



LDA 


FR0, X 


ADC 


FR0.X 


STA 


FR0,X 


DEX 




BNE 


:IFP2 


DEY 




BNE 


:IFP1 


CLD 




j SET 


EXPONENT 


LDA 


#$42 


STA 


FR0 


JMP 


NORM 



GET BYTE 

DOUBLE [ADDING IN CARRY 

FROM SHIFT 

SAVE 

DECREMENT COUNT OF FR0 BYTES 

IF MORE TO DO, DO IT 

DECR COUNT OF INTEGER DIGITS 
IF MORE TO DO, DO IT 
CLEAR DECIMAL MODE 



INDICATE DECIMAL AFTER LAST 

DIGIT 

STORE EXPONENT 



I NORMALIZE 



FPI — Convert Floating Point to Integer 

* ON ENTRY FR0 



ON EXIT 



FLOATING POINT NUMBER 
FR0 - INTEGER 



CC SET CARRY CLEAR - NO ERROR 
CARRY SET - ERROR 



CLEAR INTEGER 



D9D2 


A900 




LDA 


#0 


D9D4 


85F7 




STA 


ZTEMP4 


D9D6 


85F8 




STA 


ZTEMP4+1 
CHECK EXPONE 


D9D8 


A5D4 




LDA 


FR0 


D9DA 


3066 


"DA42 


BMI 


: ERVAL 


D9DC 


C943 




CMP 


#$43 


D9DE 


B062 


~DA42 


BCS 


: ERVAL 


D9E0 


38 




SEC 




D9E1 


E940 




SBC 


#$40 


D9E3 


903F 


"DA24 


BCC 


: ROUND 



D9E5 6900 
D9E7 

D9E7 +0A 
D9E8 85F5 



,- CLEAR INTEGER RESULT 



GET EXPONENT 

IF SIGN OF FP# IS -, THEN 

ERROR 

IS FP# TOO BIG TO BE INTEGER 

IF YES, THEN ERROR 

SET CARRY 

IS FP# LESS THAN 1? 

IF YES, THEN GO TEST FOR 

ROUND 



GET # OF DIGITS TO CONVERT 
[A CONTAINS EXPONENT -40] 
[CARRY SET] 



[EXPONENT -40+1 ]*2 



ADC 


#0 


ASLA 




ASL 


A 


STA 


ZTEMP1 


DO 


CONVERT 



; ADD IN CARRY 
; MULT BY 2 



SAVE AS COUNTER 



253 



Source Code 



MULT INTEGER RESULT BY 10 



D9EA 205ADA 
D9ED B053 "DA42 



D9EF 


A5F7 




D9F1 


85F9 




D9F3 


A5F8 




D9F5 


85FA 




D9F7 


205ADA 


D9FA 


B046 


~DA42 


D9FC 


205ADA 


D9FF 


B041 


"DA42 


DA01 


18 




DA02 


A5F8 




DA04 


65FA 




DA06 


85F8 




DA08 


A5F7 




DA0A 


65F9 




DA0C 


85F7 




DA0E 


B032 


"DA42 



JSR 


ILSHFT ; 


BCS 


ERVAL ; 


LDA ZTEMP4 ; 


STA ZTEMP3 ; 


LDA ZTEMP4+1 ; 


STA ZTEMP3+1 ; 


JSR 


ILSHFT i 


BCS 


ERVAL j 


JSR 


ILSHFT ; 


BCS 


ERVAL 


CLC 




LDA ZTEMP4+1 ; 


ADC ZTEMP3+1 ; 


STA ZTEMP4+1 ; 


LDA ZTEMP4 ; 


ADC ZTEMP3 ; 


STA ZTEMP4 ; 


BCS 


ERVAL ; 



GO SHIFT ONCE LEFT 

IF CARRY SET THEN # TOO BIG 

SAVE INTEGER *2 

X 

X 

X 



MULT BY *2 
# TOO BIG 
MULT BY *2 [NOW 
BR IF # TOO BIG 



8 IN ZTEMP4] 



ADD IN * 2 TO = *1B 

X 

X 

X 

X 

X 

X 

IF CARRY SET ERROR 



ADD IN NEXT DIGIT 



DA10 


20B9DC 


JSR 


:GETDIG 


DAI 3 


18 




CLC 




DA14 


65F8 




ADC 


ZTEMP4+1 


DA16 


85F8 




STA 


ZTEMP4+I 


DA18 


A5F7 




LDA 


ZTEMP4 


DAI A 


6900 




ADC 


#0 


DA1C 


B024 


"DA42 


BCS 


: ERVAL 


DA1E 


85F7 




STA 


ZTEMP4 


DA20 


C6F5 


" 


DEC 


ZTEMP1 


DA22 


D0C6 


"D9EA 


BNE 


:FPI1 



ROUND IF NEEDED 



DA24 




: ROUND 




DA24 


20B9DC 


JSR 


:GETDIG 


DA27 


C905 


CMP 


#5 


DA29 


900D "DA38 


BCC 


:NR 


DA2B 


18 


CLC 




DA2C 


A5F8 


LDA 


ZTEMP4+1 


DA2E 


6901 


ADC 


#1 


DA30 


85F8 


STA 


ZTEMP4+1 


DA32 


A5F7 


LDA 


ZTEMP4 


DA34 


6900 


ADC 


#0 


DA36 


85F7 


STA 


ZTEMP4 



GET DIGIT IN A 

ADD IN DIGIT 

X 

X 

X 

BR IF OVERFLOW 



DEC COUNTER OF DIGITS TO DO 
IF MORE TO DO, DO IT 



GET NEXT DIGIT IN A 

IS DIGIT <5? 

IF YES, DON'T ROUND 

ADD IN 1 TO ROUND 

X 

X 

X 

X 

X 

X 



MOVE INTEGER TO FR0 



DA38 




DA38 


A5F8 


DA3A 


85D4 


DA3C 


A5F7 


DA3E 


85D5 


DA40 


18 


DA41 


60 


DA42 




DA42 


38 


DA43 


60 



LDA 
STA 
LDA 
STA 

CLC 
RTS 



ERVAL 
SEC 
RTS 



ZTEMP4+1 
FR0 

ZTEMP4 
FR0+1 



GET INTEGER LOW 

SAVE 

GET INTEGER HIGH 

SAVE 

CLEAR CC FOR GOOD RETURN 



SET CARRY FOR ERROR RETURN 



ZFR0 - ZERO FR0 

ZF1 - ZERO 6 BYTES AT LOC X 



254 



Source Code 



ZXLY - ZERO PAGE ZERO LOC X FOR LENGTH Y 



DA44 




DA44 


A2D4 


DA46 




DA46 


A006 


DA48 




DA48 


A900 


DA4A 




DA4A 


9500 


DA4C 


E8 


DA4D 


88 


DA4E 


D0FA 


DA50 


60 



LDY 


#6 


LDA 


#0 


STA 


0. 


INX 




DEY 




BNE 


:Z 


RTS 





GET POINTER TO FR1 

GET # OF BYTES TO CLEAR 

CLEAR A 

CLEAR A BYTE 
POINT TO NEXT BYTE 
DEC COUNTER 
LOOP 



INTLBF - INIT LBUFF INTO INBUFF 



DA51 




DA51 


A905 


DA53 


85F4 


DA55 


A980 


DA57 


85F3 


DA59 


60 


DA5A 




DA 5 A 




DA 5 A 


18 


DA5B 


26F8 


DA5D 


26F7 


DA5F 


60 



INTLBF 




LDA 


#LBUFF/256 


STA 


INBUFF+1 


LDA 


#LBUFF&255 


STA 


INBUFF 


RTS 




* 




* 


: ILSHFT - SHIF 


ILSHFT 




:ILSHFT 




CLC 




ROL 


ZTEMP4+1 


ROL 


ZTEMP4 


RTS 





SHIFT INTEGER IN ZTEMP4 LEFT ONCE 



CLEAR CARRY 
SHIFT LOW 
SHIFT HIGH 



Floating Point Routines 
FADD — Floating Point Add Routine 

ADDS VALUES IN FR0 AND FR1 
* 

* ON ENTRY FR0 6> FR1 - CONTAIN # TO ADD 
* 

* ON EXIT FR0 - RESULT 

FSUB — Floating Point Subtract Routine 

* SUBTRACTS FR1 FROM FR0 
* 

* ON ENTRY FR0 S, FR1 - CONTAIN # TO SUBTRACT 

* 

* ON EXIT FR0 - RESULT 

* 

* BOTH RETURN WITH CC SET: 

* CARRY SET IF ERROR 

* CARRY CLEAR IF NO ERROR 



DA60 

DA60 A5E0 

DA62 4980 

DA64 85E0 



LDA 
EOR 
STA 



FRI 

#$80 

FRI 



GET EXPONENT OF FRI 
CHANGE SIGN OF MANTISSA 
SAVE EXPONENT 



DA66 
DA66 



FADD 
:FRADD 



255 



Source Code 



DA66 


A5E0 


DA68 


297P 


DA6A 


85F7 


DA6C 


A5D4 


DA6E 


297F 


DA70 


38 


DA71 


E5P7 


DA73 


1010 "DA85 



LDA 
AND 
STA 
LDA 
AND 
SEC 
SBC 
BPL 



FR1 
#$7F 
ZTEMP4 
FR0 

#$7F 

ZTEMP4 
:NSWAP 



DA75 A205 



SWAP FR0 AND FR1 
LDX KFMPREC 



GET EXPONENT FR1 

TURN OFF MANTISSA SIGN BIT 

SAVE TEMPORARILY 

GET EXPONENT FR0 

TURN OFF MANTISSA SIGN BIT 

CLEAR CARRY 

SUB EXPONENTS 

IF EXP[FR0]>= EXP[FR1], 

NO SWAP 



GET INDEX 



DA77 






:SWAP 


DA77 


B5D4 




LDA 


DA79 


B4E0 




LDY 


DA7B 


95E0 




STA 


DA7D 


98 




TYA 


DA7E 


95D4 




STA 


DA80 


CA 




DEX 


DA81 


10F4 


"DA77 


BPL 


DA83 


30E1 


~DA66 


BMI 


DA85 






:NSWAP 


DA85 


F007 


"DA8E 


BEQ 


DA87 


C905 




CMP 


DA89 


B019 


"DAA4 


BCS 


DA8B 


203EDC 


JSR 



FR0,X 
FR1,X 
FR1.X 

FR0,X 

:SWAP 
:FRADD 



»FMPREC 
: ADDEND 



GET BYTE FROM FR0 

GET BYTE FROM FR1 

PUT FR0 BYTE IN FR1 

GET FR1 BYTE 

PUT FR1 BYTE IN FR0 

DEC INDEX 

IF MORE TO DO, GO SWAP 

UNCONDITIONAL 



IF DIFFERENCE = 0, ALREADY 

ALIGNED 

IS DIFFERENCE < I OF BYTES 

IF NOT, HAVE RESULT IN FR0 



RSHFT1 ; 

TEST FOR LIKE SIGN OF 



DA8E 




:NALIGN 




DA8E 


F8 


SED 




DA8F 


A5D4 


LDA 


FR0 


DA91 


45E0 


EOR 


FR1 ; 


DA93 


30 IE "DAB 3 


BMI 


:SUB ; 






; ADD 


FR0 & FR1 


DA95 


A204 


LDX 


#FMPREC-1 ; 


DA97 


18 


CLC 




DA98 




:ADD1 




DA98 


B5D5 


LDA 


FR0M.X ; 


DA9A 


75E1 


ADC 


FR1M,X ; 


DA9C 


95D5 


STA 


FR0M,X ; 


DA9E 


CA 


DEX 




DA9F 


10F7 "DA98 


BPL 


:ADD1 ! 


DAA1 


D8 


CLD 




DAA2 


B003 ~DAA7 


BCS 


:ADD2 ; 


DAA4 




: ADDEND 




DAA4 


4C00DC 


JMP 


NORM ; 






; ADD 


IN FIND CARRY 


DAA7 




:ADD2 




DAA7 


A901 


LDA 


#i ; 


DAA9 


203ADC 


JSR 


RSHFT0 ; 


DAAC 


A901 


LDA 


#01 ; 


DAAE 


85D5 


STA 


FR0M ; 


DAB0 


4C00DC 


JMP 


NORM 



SHIFT TO ALIGN 
MANTISSA 



SET DECIMAL MODE 

GET FR0 EXPONENT 

EOR WITH FR1 EXPONENT 

IF SIGNS DIFFERENT - SUBTRACT 

ELSE ADD 



GET POINTER FOR LAST BYTE 
CLEAR CARRY 

GET BYTE OF FR0 

ADD IN BYTE OF FR1 

STORE 

DEC POINTER 

ADD NEXT BYTE 

CLEAR DECIMAL MODE 

IF THERE IS A CARRY, DO IT 

GO NORMALIZE 



GET 1 TIMES TO SHIFT 
GO SHIFT 



GET CARRY 
ADD IN CARRY 



DAB 3 

DAB3 A204 

DAB 5 38 



SUBTRACT FR1 FROM FR0 



LDX 

SEC 



#FMPREC-1 



GET POINTER TO LAST BYTE 
SET CARRY 



256 



Source Code 



DAB 6 






:SUB1 




DAB 6 


B5D5 




LDA 


FR0M.X 


DAB 8 


F5E1 




SBC 


FR1M,X 


DABA 


95D5 




STA 


FR0M.X 


DABC 


CA 




DEX 




DABD 


10F7 


"DAB 6 


BPL 


:SUB1 


DABF 


9004 


"DAC5 


BCC 


:SUB2 


DAC1 


D8 




CLD 




DAC2 


4C00DC 


JMP 


NORM 



DAC5 

DAC5 A5D4 

DAC7 4980 

DAC9 85D4 



SUB2 
LDA 
EOR 
STA 



TAKE COMPLEMENT SIGN 

FR0 

#$80 

FR0 

COMPLEMENT MANTISSA 



GET FR0 BYTE 

SUB FR1 BYTE 

STORE 

DEC POINTER 

SUB NEXT BYTE 

IF THERE IS A BORROW DO IT 
CLEAR DECIMAL MODE 



GET EXPONENT 

CHANGE SIGN OF MANTISSA 

PUT IT BACK 



DACB 


38 


DACC 


A204 


DACE 




DACE 


A900 


DAD0 


F5D5 


DAD2 


95D5 


DAD4 


CA 


DAD5 


10F7 * 


DAD7 


D8 


DAD8 


4C00DC 



SEC 
LDX 
:SUB3 

LDA 
SBC 
STA 
DEX 
BPL 

CLD 

JMP 



#FMPREC-1 

#0 

FR0M,X 

FR0M.X 

:SUB3 



SET CARRY 

GET INDEX COUNTER 

GET ZERO 
COMPLEMENT BYTE 
STORE 

MORE TO DO 
BR IF YES 

; CLEAR DECIMAL MODE 
I GO NORMALIZE 



FMUL — Multiply FRO by FR1 



ON ENTRY # ARE IN FR0 AND FR1 

ON EXIT FR0 - CONTAINS PRODUCT 

RETURN WITH CC SET 

CARRY SET IF ERROR 
CARRY CLEAR IF NO ERROR 



SET UP EXPONENT 



DADB 


A5D4 


LDA 


DADD 


F045 "DB24 


BEQ 


DADF 


A5E0 


LDA 


DAE1 


F03E "DB21 


BEQ 


DAE 3 


20CFDC 


JSR 


DAE 6 


38 


SEC 


DAE 7 


E940 


SBC 


DAE 9 


38 


SEC 


DAEA 


65E0 


ADC 


DAEC 


3038 "DB26 


BMI 



FR0 
MEND3 
FR1 
MEND2 

MDESUP 

#540 

FR1 
:EROV 



GET EXP FR0 

IF = 0, DONE 

GET FR1 EXP 

IF =0, ANSWER =0 

DO COMMON SET FOR EXPONENT 
SET CARRY 
SUB EXCESS 64 
SET CARRY TO ADD 1 
ADD 1 + FR1 EXP TO FR0 EXP 
IF - THEN OVERFLOW 



FINISH MULTIPLY SET UP 



DAEE 20E0DC 



DO SET UP COMMON TO DIVIDE 



DO THE MULTIPLY 



GET * OF TIMES TO ADD IN MULTIPLICAND 



257 



Source Code 



DAFl 


A5DF 


LDA 


FRE+FMPREC 


DAF3 


290F 


AND 


#$0F 


DAF5 


85F6 


STA 


ZTEMP1+1 






ADD 


IN FR1 


DAF7 




FRM1 




DAF7 


C6F6 


DEC 


ZTEMP1+1 


DAF9 


3006 ~DB01 


BMI 


:FRM2 


DAFB 


2001DD 


JSR 


FRA10 


DAFE 


4CF7DA 


JMP 


:FRM1 



GET LAST BYTE OF FRE 

AND OUT HIGH ORDER NIBBLE 

SET COUNTER FOR LOOP CONTROL 



DEC MULT COUNTER 

IF - THIS LOOP DONE 

ADD FR1 TO FR0 [6 BYTES] 

REPEAT 



DB01 




FRM2 




DB01 


A5DF 


LDA 


FRE+FMPREC 


DB03 




LSRA 




DB03 
DB04 


+4A 


LSR 

LSRA 


A 


DB04 


+4A 


LSR 


A 


DB05 




LSRA 




DB05 


+4A 


LSR 


A 


DB06 




LSRA 




DB06 


+4A 


LSR 


A 


DB07 


85F6 


STA 


ZTEMP1+1 






ADD 


IN FR2 


DB09 




FRM3 




DB09 


C6F6 


DEC 


ZTEMP1+1 


DB0B 


3006 "DB13 


BMI 


:NXTB 


DB0D 


2005DD 


JSR 


FRA20 


DB10 


4C09DB 


JMP 


:FRM3 



GET # OF TIMES TO ADD IN MULTIPLICAND * 10 



; GET LAST BYTE OF FRE 

; SHIFT OUT LOW ORDER NIBBLE 

; X 

; x 

; x 

; SAVE AS COUNTER 



DECREMENT COUNTER 

IF -, DO NEXT BYTE 

ADD FR2 TO FR0 [6 BYTES] 

REPEAT 



DB13 2062DC 



DB16 C6F5 

DB18 D0D7 "DAFl 



SET UP FOR NEXT SET OF ADDS 

TB 

SHIFT FR0/FRE RIGHT ONE BYTE 
[THEY ARE CONTIGUOUS] 

JSR RSHF0E ; SHIFT FR0/FRE RIGHT 

TEST FOR # OF BYTES SHIFTED 



DEC 
BNE 



ZTEMP1 
:FRM 



DECREMENT LOOP CONTROL 
IF MORE ADDS TO DO, DO IT 



SET EXPONENT 



DB1A 




MDEND 




DB1A 


A5ED 


LDA 


EEXP 


DB1C 


85D4 


STA 


FR0 


DB1E 




MEND1 




DB1E 


4C04DC 


JMP 


NORM 


DB21 




MEND2 




DB21 


2044DA 


JSR 


ZFR0 


DB24 




MEND3 




DB24 


18 


CLC 




DB25 


60 


RTS 





GET EXPONENT 
STORE AS FR0 EXP 



; NORMALIZE 



CLEAR FR0 

CLEAR CARRY FOR GOOD RTN 



DB26 

DB26 38 
D327 60 



:EROV 

SEC 
RTS 



SET CARRY FOR ERROR ROUTINE 
RETURN 



258 



Source Code 



FDIV — Floating Point Divide 



ON ENTRY 


FR0 - 
FR1 ■ 


- DIVIDEND 

- DIVISOR 


ON EXIT 


FR0 


- QUOTIENT 



RETURNS WITH CC SET: 

CARRY CLEAR - ERROR 
CARRY SET - NO ERROR 









DO 


DIVIDE SET UP 


DB28 


A5E0 


LDA 




FR1 


DB2A 


F0FA ~DB26 


BEQ 




:EROV 


DB2C 


A5D4 


LDA 




FR0 


DB2E 


F0F4 ~DB24 


BEQ 




MEND3 


DB30 


20CFDC 


JSR 




MDESUP 


DB33 


38 


SEC 






DB34 


E5E0 


SBC 




FR1 


DB36 


18 


CLC 






DB37 


6940 


ADC 




#540 


DB39 


30EB *DB26 


BMI 




:EROV 


DB3B 


20E0DC 


JSR 




MDSUP 


DB3E 


E6F5 


INC 




ZTEMP1 


DB40 


4C4EDB 


JMP 




:FRD1 




= 00D9 


QTEMP 


EQU 


FR0+FMPREC 


DB43 




:NXTQ 







GET FR1 EXP 
IF =0, THEN OVERFLOW 
GET EXPONENT FR0 
IF = 0, THEN DONE 

DO COMMOM PART OF EXP SET UP 



; SUB FR1 EXP FROM FR0 EX 

; ADD IN EXCESS 64 

; IF MINUS THEN OVERFLOW 

; DO SETUP COMMON FOR MULT 
;LOOP 1 MORE TIME FOR DIVIDE 
; SKIP SHIFT 1ST TIME THROUGH 



SHIFT FR0/FRE LEFT ONE BYTE 

[THEY ARE CONTIGUOUS] 



DB43 


A200 




LDX 




#0 


DB45 






:NXTQ1 






DB45 


B5D5 




LDA 




FR0+1,X 


DB47 


95D4 




STA 




FR0,X 


DB49 


E8 




INX 






DB4A 


E00C 




CPX 




#FMPREC*2+2 


DB4C 


D0F7 


"DB45 


BNE 




:NXTQ1 








* 


DO 


DIVIDE 



GET POINTER TO BYTE TO MOVE 

GET BYTE 

MOVE IT LEFT ONE BYTE 

POINT TO NEXT BYTE 
HAVE WE DONE THEM ALL? 
IF NOT, BRANCH 



DB4E 


A005 


LDY 


#FMPREC 


DB50 


38 


SEC 




DB51 


F8 


SED 




DB52 




:FRS2 




DB52 


B9DA00 


LDA 


FRE, Y 


DB55 


F9E600 


SBC 


FR2, Y 


DB58 


99DA00 


STA 


FRE, Y 


DB5B 


88 


DEY 




DB5C 


10F4 "DB52 


BPL 


:FRS2 


DB5E 


D8 


CLD 




DB5F 


9004 "DB65 


BCC 


:FAIL 


DB61 


E6D9 


INC 


QTEMP 



SUBTRACT FR2 [DIVISOR * 2] FROM FRE [DIVIDEND] 



SET LOOP CONTROL 

SET CARRY 

SET DECIMAL MODE 

; GET A BYTE FROM FRE 

; SUB FR2 

; STORE RESULT 

; DEC COUNTER 

; BR IF MORE TO DO 

; CLEAR DECIMAL MODE 



■ IF RESULT <0 [FRE < FR2 ] BR 
; INCR # TIMES SUB [QUOTIENT] 



259 



Source Code 



DB63 D0E9 ~DB4E 



DB65 




FAIL 




DB65 


200FDD 


JSR 


FRA2E 
SHIFT LAS 


DB68 


06D9 


ASL 


QTEMP 


DB6A 


06D9 


ASL 


QTEMP 


DB6C 


06D9 


ASL 


QTEMP 


DB6E 


06D9 


ASL 


QTEMP 


DB70 




FRD2 





BNE :FRD1 ; SUB AGAIN 

SUBTRACT OF FR2 DIDN'T GO 

I ADD FR2 BACK TO FR0 
SHIFT LAST BYTE OF QUOTIENT ONE NIBBLE LEFT 



SHIFT 4 BITS LEFT 

X 

X 

X 



SUBTRACT FR1 [DIVISOR] FROM FRE [DIVIDEND] 



DB70 


A005 




LDY 


#FMPREC 


DB72 


38 




SEC 




DB73 


F8 




SED 




DB74 






:FRS1 




DB74 


B9DA00 




LDA 


FRE, Y 


DB77 


F9E000 




SBC 


FR1,Y 


DB7A 


99DA00 




STA 


FRE, Y 


DB7D 


88 




DEY 




DB7E 


10F4 * 


DB74 


BPL 


:FRS1 


DB80 


D8 




CLD 




DB81 


9004 * 


DB87 


BCC 


:FAIL2 


DB83 


E6D9 




INC 


QTEMP 


DB85 


D0E9 * 


DB70 


BNE 


:FRD2 



SET LOOP CONTROL 

SET CARRY 

SET DECIMAL MODE 

GET A BYTE FROM FRE 
SUB FR1 
STORE RESULT 

BR IF MORE TO DO 
CLEAR DECIMAL MODE 

IF RESULT < [FRE < FR1] BR 

INCR # TIMES SUB [QUOTIENT] 

SUB AGAIN 



SUBTRACT OF FR1 DIDN'T GO 



DB87 




:FAIL2 




DB87 


2009DD 


JSR 


FRA1E 


DB8A 


C6F5 


DEC 


ZTEMP1 


DB8C 


D0B5 "DB43 


BNE 


:NXTQ 


DB8E 


2062DC 


JSR 


RSHF0E 


DB91 


4C1ADB 


JMP 


MDEND 


:GETCHAR — Testlni 


mt Character 





ON ENTRY 



| ADD FR1 BACK TO FR0 

I DEC LOOP CONTROL 

; GET NEXT QUIOTIENT BYTE 

; SHIFT RIGHT FR0/FRE TO CLEAR 

EXP 
j JOIN MULT END UP CODE 



INBUFF - POINTS TO BUFFER WITH INPUT 
CIX - POINTS TO CHAR IN BUFFER 



CIX - POINTS TO NEXT CHAR 
CC - CARRY CLEAR IF CHAR IS NUMBER 
CARRY SET IF CHAR NOT NUMBER 



DB94 




:GETCHAR 




DB94 


20AFDB 


JSR 


TSTNUM 


DB97 


A4F2 


LDY 


CIX 


DB99 


9002 "DB9D 


BCC 


:GCHR1 


DB9B 


B1F3 


LDA 


[INBUFF], Y 


DB9D 




:GCHR1 




DB9D 


C8 


I NY 




DB9E 


84F2 


STY 


CIX 


DBA0 


60 


RTS 





GO TEST FOR NUMBER 
GET CHARACTER INDEX 
IF CHAR = NUM, SKIP 

GET CHARACTER 



POINT TO NEXT CHAR 
SAVE INDEX 



;SKPBLANK-SKIP BLANKS 

STARTS AT CIX AND SCANS FOR NON BLANKS 



260 



Source Code 



DBAl 






SKBLANK 














DBAl 






SKPBLANK 












DBAl 


A4F2 




LDY 




CIX 




;GET CIX 




DBA 3 


A920 




LDA 




#520 




;GET A BLANK 




DBA 5 


D1F3 




tSBl 


CMP 


[INBUFF], 


Y ;IS CHAR A 


BLANK 


DBA7 


D003 


"DBAC 


BNE 




:SBRTS 






BR IF NOT 




DBA9 


C8 




I NY 










INC TO NEXT 




DBAA 


D0F9 


"DBA5 


BNE 




:SB1 






GO TEST 




DBAC 


84F2 




:SBRTS 


STY 


CIX 




;SET NON BLANK 


INDEX 


DBAE 


60 




RTS 








; RETURN 










; TSTNUM 


-TEST CHAR AT CIX FOR NUM 












- RTNS CARRY 


SET 


IF NUM 




DBAF 






TSTNUM 












DBAF 


A4F2 




LDY 




CIX 




;GET INDEX 




DBB1 


B1F3 




LDA 




[INBUFF], 


Y 


;AND GET CHAR 




DBB3 


38 




SEC 












DBB4 


E930 




SBC 




#?30 






SUBTRACT ASCLT ZERO 


DBB6 


9018 


"DBD0 


BCC 




:TSNFAIL 






BR CHAR<ASCLT 


ZERO 


DBB8 


C90A 




CMP 




#$0A 






TEST GT ASCLT 


9 


DBBA 


60 




RTS 










DONE 





:TSTCHAR — Test to See if This Can Be a Number 









* ON 

* 


EXIT C 


DBBB 






* 
tTSTCHAR 




DBBB 


A5F2 




LDA 


CIX 


DBBD 


48 




PHA 




DBBE 


2094DB 


JSR 


:GETCHAR 


DBC1 


901F 


"DBE2 


BCC 


:RTPASS 


DBC3 


C92E 




CMP 


#' . ' 


DBC5 


F014 


"DBDB 


BEQ 


:TSTN 


DBC7 


C92B 




CMP 


#'+' 


DBC9 


F007 


"DBD2 


BEQ 


:TSTN1 


DBCB 


C92D 




CMP 


#'-' 


DBCD 


F003 


"DBD2 


BEQ 


:TSTN1 


DBCF 






:RTFAIL 





DBCF 






RTFAIL 




DBCF 


68 




PLA 




DBD0 


38 




TSNFAIL 


SEC 


DBD1 


60 




RTS 




DBD2 






TSTN1 




DBD2 


2094DB 


JSR 


:GETCHAR 


DBD5 


900B 


"DBE2 


BCC 


: RTPASS 


DBD7 


C92E 




CMP 


#'.' 


DBD9 


D0F4 


"DBCF 


BNE 


: RTFAIL 


DBDB 






TSTN 




DBDB 


2094DB 


JSR 


:GETCHAR 


DBDE 


9002 


"DBE2 


BCC 


: RTPASS 


DBE0 


B0ED 


"DBCF 


BCS 


: RTFAIL 


DBE2 






RTPASS 




DBE2 


68 




PLA 




DBE3 


85F2 




STA 


CIX 


DBE5 


18 




CLC 




DBE6 


60 




RTS 





CC - CARRY SET IF NOT A # 
CARRY CLEAR IF A # 



GET INDEX 

SAVE IT 

GET CHAR 

IF = #8 RETURN PASS 

IF = D.P. , OK SO FAR 

IF = +8 OK SO FAR 

IF = -8 OK SO FAR 



; CLEAR STACK 
;SET FAIL 



GET CHAR 

IF #, RETURN PASS 

IS IT D.P. 

IF NOT, RETURN FAIL 

ELSE GET NEXT CHAR 
IF #, RETURN PASS 
ELSE, RETURN FAIL 



RESTORE CIX 

X 

CLEAR CARRY 

RETURN PASS 



NIBSHO — Shift FRO One Nibble Left 

* NIBSH2 - SHIFT FR2 ONE NIBBLE LEFT 



DBE7 

DBE7 A2E7 



NIBSH2 
LDX 



#FR2+1 



POINT TO 1ST MANTISSA BYTE 



261 



Source Code 



DBE9 D002 "DBED 



DBEB 




DBEB 


A2D5 


DBED 




DBED 


A004 


DBEF 




DBEF 


18 


DBF0 


3604 


DBF2 


3603 


DBF4 


3602 


DBF6 


3601 


DBF8 


3600 


DBFA 


26EC 


DBFC 


88 


DBFD 


D0F0 


DBFF 


60 


NORM — N 


DC00 




DC00 


A200 


DC02 


86DA 


DC04 




DC04 


A204 


DC06 


A5D4 


DC08 


F02E 


DC0A 




DC0A 


A5D5 


DC0C 


D01A 



LDX 


#FR0M 


:NIB1 




LDY 


#4 


:NIBS 




CLC 




ROL 


4,X 


ROL 


3,X 


ROL 


2,X 


ROL 


l.X 


ROL 


0,X 


ROL 


FRX 


DEY 




BNE 


:NIBS 


RTS 





"DC38 



DC0E 


A000 


DC10 




DC10 


B9D600 


DC13 


99D500 


DC16 


C8 


DC17 


C005 



DC19 90F5 ~DC10 



DC1B C6D4 



NORM 




LDX 


#0 


STX 


FR0+FPREC 


NORM1 




LDX 


#FMPREC-1 


LDA 


FR0 


BEQ 


:NDONE 


:NORM 




LDA 


FR0M 


BNE 


:TSTBIG 




SHIFT 1 BYTE 


LDY 


#0 


:NSH 




LDA 


FR0M+1, Y 


STA 


FR0M, Y 


INY 




CPY 


#FMPREC 


BCC 


:NSH 



POINT TO MANTISSA OF FR0 

GET # OF BITS TO SHIFT 

CLEAR CARRY 

ROLL 

X 

X 

X 

X 

SAVE SHIFTED NIBBLE 

DEC COUNT 

IF NOT = 0, REPEAT 



GET ZERO 

FOR ADD NORM SHIFT IN A ZERO 

GET MAX # OF BYTES TO SHIFT 
GET EXPONENT 
IF EXP=0, # =0 

GET 1ST BYTE OF MANTISSA 
IF NOT = THEN NO SHIFT 



GET INDEX FOR 1ST MOVE BYTE 



DECREMENT EXPONENT 
DEC FR0 



GET MOVE BYTE 
STORE IT 



ARE WE DONE 

IF NOT SHIFT AGAIN 



DECREMENT EXPONENT 



DC1D 


CA 




DEX 




DC1E 


D0EA 


"DC0A 


BNE 


:NORM 


DC20 


A5D5 




LDA 


FR0M 


DC22 


D004 


"DC28 


BNE 


:TSTBIG 


DC24 


85D4 




STA 


FR0 


DC26 


18 




CLC 




DC27 


60 




RTS 




DC28 






:TSTBIG 




DC28 


A5D4 




LDA 


FR0 


DC 2 A 


297F 




AND 


#$7F 


DC2C 


C971 




CMP 


#49+64 


DC2E 


9001 


"DC31 


BCC 


:TSTUND 


DC30 


60 




RTS 




DC31 






:TSTUND 




DC31 


C90F 




CMP 


#-49+64 


DC33 


B003 


"DC38 


BCS 


:NDONE 


DC35 


2044DA 


JSR 


ZFR0 


DC38 






:NDONE 




DC38 


18 




CLC 




DC39 


60 




RTS 





DEC COUNTER 

DO AGAIN IF NEEDED 



IS MANTISSA STILL 

IF NOT, SEE IF TOO BIG 

ELSE ZERO EXP 



GET EXPONENT 

AND OUT SIGN BIT 

IS IT < 49+64? 

IF YES, TEST UNDERFLOW 

SO RETURN 

IS IT >=-49+64? 

IF YES, WE ARE DONE 

ELSE # IS ZERO 



CLEAR CARRY FOR GOOD RETURN 



262 



Source Code 



RSHFTO — Shift FRO Right/Increment Exponent 
RSHFT1 — Shift FR1 Right/Increment Exponent 









* 
* 


ON ENTRY A 


DC 3 A 






* 
RSHFT0 




DC 3 A 


A2D4 




LDX 


#FR0 


DC3C 


D002 


"DC40 


BNE 


:RSH 


DC3E 






RSHFT1 




DC3E 


A2E0 




LDX 


#FR1 


DC40 






:RSH 




DC40 


86F9 




STX 


ZTEMP3 


DC42 


85F7 




STA 


ZTEMP4 


DC44 


85F8 




STA 


ZTEMP4+1 


DC46 






:RSH2 




DC46 


A004 




LDY 


#FMPREC-1 


DC48 






:RSH1 




DC48 


B504 




LDA 


4,X 


DC 4 A 


9505 




STA 


5,X 


DC4C 


CA 




DEX 




DC4D 


88 




DEY 




DC4E 


D0F8 


"DC48 


BNE 


:RSH1 


DC50 


A900 




LDA 


#0 


DC52 


9505 




STA 


5,X 


DC 54 


A6F9 




LDX 


ZTEMP3 


DC 56 


C6F7 




DEC 


ZTEMP4 


DC 58 


D0EC 


"DC46 


BNE 


:RSH2 
FIX EXPONENT 


DC 5 A 


B500 




LDA 


0,X 


DC5C 


18 




CLC 




DC5D 


65F8 




ADC 


ZTEMP4+1 


DC5F 


9500 




STA 


0,X 


DC61 


60 




RTS 





A - # OF PLACES TO SHIFT 



POINT TO FR0 



POINT TO FR1 



SAVE FR POINTER 

SAVE # OF BYTES TO SHIFT 

SAVE FOR LATER 



GET # OF BYTES TO MOVE 

GET CHAR 

STORE CHAR 

POINT TO NEXT BYTE 

DEC LOOP CONTROL 

IF MORE TO MOVE, DO IT 

GET 1ST BYTE 

STORE IT 

GET FR POINTER 

DO WE NEED TO SHIFT AGAIN? 

IF YES, DO IT 



GET EXPONENT 



SUB # OF SHIFTS 
SAVE NEW EXPONENT 



RSHFOE — Shift FRO/FRE 1 Byte Right [They Are Contiguous] 



DC62 






RSHF0E 




DC62 


A20A 




LDX 


#FMPREC*2 


DC64 






:NXTB1 




DC64 


B5D4 




LDA 


FR0.X 


DC66 


95D5 




STA 


FR0+1,X 


DC68 


CA 




DEX 




DC69 


10F9 


"DC64 


BPL 


:NXTB1 


DC6B 


A900 




LDA 


#0 


DC6D 


85D4 




STA 


FR0 


DC6F 


60 




RTS 





GET LOOP CONTROL 



GET A BYTE 
MOVE IT OVER 1 

DEC COUNTER 
MOVE NEXT BYTE 
GET ZERO 
SHIFT IT IN 



:CVFR0 — Convert Each Byte in FRO to 2 Characters in LBUFF 







* 


ON 


ENTRY 






* 










* 






DC70 




:CVFR0 






DC70 


85F7 


STA 




ZTEMP4 


DC72 


A200 


LDX 




#0 


DC74 


A000 


LDY 




#0 



DECIMAL POINT POSITION 



SAVE DECIMAL POSITION 

SET INDEX INTO FR0M 
SET INDEX INTO OUTPUT 
LINE [LBUFF] 



CONVERT A BYTE 



263 



Source Code 



DC76 




:CVBYTE 






DC76 


2033DC 


JSR 


:TSTDP 


; PUT IN D.P. NOW? 


DC79 




:CVB1 






DC79 


38 


SEC 




; DECREMENT DECIMAL 


DC 7 A 


E901 


SBC 


#1 


; X 


DC7C 


85F7 


STA 

; DO 


ZTEMP4 
1ST DIGIT 


; SAVE IT 


DC7E 


B5D5 


LDA 


FR0M.X 


; GET FROM FR0 


DC 80 




LSRA 




; SHIFT OUT LOW ORDE 


DC80 


+4A 


LSR 


A 




DC81 




LSRA 




; TO GET 1ST DIGIT 


DC81 


+4A 


LSR 


A 




DC82 




LSRA 




; X 


DC82 


+4A 


LSR 


A 




DC83 




LSRA 




; x 


DC83 


+4 A 


LSR 


A 




DC84 


209DDC 


JSR 


:STNUM 


; GO PUT f IN BUFFER 



DO SECOND DIGIT 



DC87 


B5D5 


LDA 




FR0M,X 


DC89 


290F 


AND 




I50F 


DC8B 


209DDC 


JSR 




:STNUM 


DC8E 


E8 


INX 






DC8F 


E005 


CPX 




#FMPREC 


DC91 


90E3 "DC76 


BCC 




:CVBYTE 








PUT IN DECK 


DC93 




TSTDP 






DC93 


A5F7 


LDA 




ZTEMP4 


DC95 


D005 ~DC9C 


BNE 




:TST1 


DC97 


A92E 


LDA 




#' . ' 


DC99 


209FDC 


JSR 




:STCHAR 


DC9C 




TST1 






DC9C 


60 


RTS 






:STNUM — Put ASCII 


Numbei 


in 


LBUFF 






h 


ON 


ENTRY 



; GET NUMBER FROM FR0 

; AND OUT HIGH ORDER BITS 

; GO PUT # IN BUFFER 

; INCR FR0 POINTER 

; DONE LAST FR0 BYTE? 

; IF NOT, MORE TO DO 



GET DECIMAL POSITION 
IF NOT = RTN 
GET ASCII DECIMAL POINT 
PUT D.P. IN BUFFER 



A - DIGIT TO BE CONVERTED TO ASCII 

AND PUT IN LBUFF 
Y - INDEX IN LBUFF 



:STCHAR — Store Character in A in LBUFF 



DC9D 




: STNUM 


DC9D 


0930 


ORA 


DC9F 




:STCHAR 


DC9F 


998005 


STA 


DC A 2 


C8 


I NY 


DC A 3 


60 


RTS 



#?30 



CONVERT TO ASCII 



PUT IN LBUFF 

INCR LBUFF POINTER 



:FNZER0 — Find Last Non-zero Character in LBUFF 







* ON 


EXIT 


A 






* 




X 






* 






DCA4 




:FNZER0 






DC A 4 


A20A 


LDX 


#10 




DC A 6 




:FN3 






DCA6 


BD8005 


LDA 


LBUFF 


X 


DC A 9 


C92E 


CMP 


#' . ' 




DCAB 


F007 "DCB4 


BEQ 


:FN1 




DCAD 


C930 


CMP 


#'0' 




DCAF 


D007 "DCB8 


BNE 


:FN2 




DCB1 


CA 


DEX 






DCB2 


D0F2 "DCA6 


BNE 


:FN3 





LAST CHAR 

POINT TO LAST CHAR 



POINT TO LAST CHAR IN LBUFF 



GET THE CHARACTER 
IS IT DECIMAL? 
IF YES, BR 
IS IT ZERO? 
IF NOT, BR 
DECREMENT INDEX 
UNCONDITIONAL BR 



264 



Source Code 



DCB4 




:FN1 




DCB4 


CA 


DEX 




DCB5 


BD8005 


LDA 


LBUFF,X 


DCB8 




:FN2 




DCBS 


60 


RTS 





:GETDIG — Get Next Digit from FRO 



DCB9 




DCB9 


20EBDB 


DCBC 


A5EC 


DCBE 


290F 


DCC0 


60 


:DECINB — D« 


DCCl 




DCC1 


38 


DCC2 


A5F3 


DCC4 


E901 


DCC6 


85F3 


DCC8 


A5F4 


DCCA 


E900 


DCCC 


85F4 


DCCE 


60 



* 


ON 


ENTRY FR0 - 1 


* 
* 


ON 


EXIT A - DIGIT 


* 
:GETDIG 






JSR 




NIBSH0 


LDA 




FRX 


AND 




#50F 


RTS 






ntlNBUFF 




: DECINB 






SEC 






LDA 




INBUFF 


SBC 




#1 


STA 




INBUFF 


LDA 




INBUFF+1 


SBC 




#0 


STA 




IH8UFF+1 


RTS 







DECREMENT BUFFER INDEX 
GET LAST CHAR 



SHIFT FR0 LEFT ONE NIBBLE 

GET BYTE CONTAINING 

SHIFTED NIBBLE 

AND OUT HIGH ORDER NIBBLE 



SUBTRACT ONE FROM INBUFF 

X 

X 

X 

X 

X 

X 



MDESUP — Common Set-up for Multiply and Divide Exponent 

* ON EXIT 



FR1 - FR1 EXP WITH OUT SIGN 
A - FR0 EXP WITHOUT SIGN 
FRSIGN - SIGN FOR QUOTIENT 



DCCF 




MDESUP 




DCCF 


A5D4 


LDA 


FR0 J 


DCD1 


45E0 


EOR 


FR1 ; 


DCD3 


2980 


AND 


#$80 


DCD5 


85EE 


STA 


FRSIGN ; 


DCD7 


06E0 


ASL 


FR1 ; 


DCD9 


46E0 


LSR 


FR1 ; 


DCDB 


A5D4 


LDA 


FR0 ; 


DCDD 


297F 


AND 


#$7F ; 


DCDF 


60 


RTS 





GET FR0 EXPONENT 

GET FR1 EXPONENT 

AND OUT ALL BUT SIGN BIT 

SAVE SIGN 

SHIFT OUT SIGN IN FR1 EXP 
RESTORE FR1 EXP WITHOUT SIGN 
GET FR0 EXP 
AND OUT SIGN BIT 



MDSUP — Common Set-up for Multiply and Divide 







+ 

* 


ON 


ENTRY 


DCE0 




MDSUP 




DCE0 


05EE 




ORA 


FRSIGN 


DCE2 


85ED 




STA 


EEXP 


DCE4 


A900 




LDA 


#0 


DCE6 


85D4 




STA 


FR0 


DCE8 


85E0 




STA 


FR1 


DCEA 


2028DD 




JSR 


MVFR12 


DCED 


20E7DB 




JSR 


NIBSH2 


DCF0 


A5EC 




LDA 


FRX 



A - EXPONENT 

CC - SET BY ADD OR SUB TO GET A 



OR IN SIGN BIT 

SAVE EXPONENT FOR LATER 

CLEAR A 

CLEAR FR0 EXP 

CLEAR FR0 EXP 



MOVE FR1 TO FR2 



; SHIFT FR2 1 NIBBLE LEFT 
; GET SHIFTED NIBBLE 



265 



Source Code 



DCF2 290F 
DCF4 85E6 



DCF6 A905 
DCF8 85F5 



DCFA 2034DD 
DCFD 2044DA 



AND 


#$0F 


STA 


FR2 


LDA 


#FMPREC 


STA 


ZTEMP1 


JSR 


MVFR0E 


JSR 


ZFR0 



; AND OUT HIGH ORDER NIBBLE 
; STORE TO FINISH SHIFT 



SET LOOP CONTROL 
X 



MOVE FR0 TO FRE 
CLEAR FR0 



FRA 



FRA10 - ADD FR1 TO FR0 [6 BYTES] 

FRA20 - ADD FR2 TO FR0 [6 BYTES] 

FRA1E - ADD FR1 TO FRE 

FRA2E - ADD FR2 TO FRE 



DD01 






FRA10 




DD01 


A2D9 




LDX 


#FR0+FMPREC 


DD03 


D006 


"DD0B 


BNE 


:F1 


DD05 






FRA20 




DD05 


A2D9 




LDX 


#FR0+FMPREC 


DD07 


D008 


'DD11 


BNE 


:F2 


DD09 






FRA1E 




DD09 


A2DF 




LDX 


#FRE+FMPREC 


DD0B 






:F1 




DD0B 


A0E5 




LDY 


#FR1+FMPREC 


DD0D 


D004 


~DD13 


BNE 


:FRA 


DD0F 






FRA2E 




DD0F 


A2DF 




LDX 


#FRE+FMPREC 


DD11 






:F2 




DD11 


A0EB 




LDY 


#FR2+FMPREC 


DD13 






:FRA 




DD13 


A905 




LDA 


#FMPREC 


DD15 


85F7 




STA 


ZTEMP4 


DD17 


18 




CLC 




DD18 


F8 




SED 




DD19 






:FRA1 




DD19 


B500 




LDA 


0,X 


DD1B 


790000 


ADC 


0,Y 


DD1E 


9500 




STA 


0,X 


DD20 


CA 




DEX 




DD21 


88 




DEY 




DD22 


C6F7 




DEC 


ZTEMP4 


DD24 


10F3 


~DD19 


BPL 


:FRA1 


DD26 


D8 




CLD 




DD27 


60 




RTS 





POINT TO LAST BYTE OF SUM 






GET VALUE FOR LOOP CONTROL 

SET LOOP CONTROL 

CLEAR CARRY 

SET DECIMAL MODE 

GET 1ST BYTE OF 

ADD 

STORE 

POINT TO NEXT BYTE 

POINT TO NEXT BYTE 

DEC COUNTER 

IF MORE TO DO, DO IT 

CLEAR DECIMAL MODE 



MVFR12 — Move FR1 to FR2 



DD28 




MVFR12 




DD28 


A005 


LDY 


#FMPREC 


DD2A 




:MV2 




DD2A 


B9E000 


LDA 


FR1, Y 


DD2D 


99E600 


STA 


FR2, Y 


DD30 


88 


DEY 




DD31 


10F7 "DD2A 


BPL 


:MV2 


DD33 


60 


RTS 





SET COUNTER 



GET A BYTE 
STORE IT 



DEC COUNTER 

IF MORE TO MOVE, 



266 



Source Code 



MVFROE — Move FRO to FRE 




DD34 




MVFR0E 




DD34 


A00 5 


LDY 


#FMPREC 


DD36 




:MV1 




DD36 


B9D400 


LDA 


FRB, Y 


DD39 


99DA00 


STA 


FRE, Y 


DD3C 


88 


DEY 




DD3D 


10F7 "DD36 


BPL 


:MV1 


DD3F 


60 


RTS 





Polynomial Evaluation 



DD40 
DD42 
DD44 
DD46 
DD48 
DD4A 
DD4D 
DD50 
DD52 
DD54 
DD57 
DD59 
DD5B 
DD5E 
DD60 
DD61 
DD63 
DD65 
DD67 
DD69 
DD6B 
DD6D 
DD6F 
DD71 
DD73 
DD76 
DD79 
DD7B 
DD7D 
DD7F 
DD81 
DD83 
DD86 
DD88 



86FE 

84FF 

85EF 

A2E0 

A005 

20A7DD 

20B6DD 

A6FE 

A4FF 

2089DD 

C6EF 

F02D "DD88 

20DBDA 

B028 "DD88 

18 

A5FE 

6906 

85FE 

9006 "DD6F 

A5FF 

6900 

85FF 

A6FE 

A4FF 

2098DD 

2066DA 

B00D "DD88 

C6EF 

F009 "DD88 

A2E0 

A005 

2098DD 

30D3 "DD5B 

60 



PLYEVL 
STY 
STA 
LDX 
LDY 
JSR 
JSR 
LDX 
LDY 
JSR 
DEC 
BEQ 

PLYEV1 
BCS 
CLC 
LDA 
ADC 
STA 
BCC 
LDA 
ADC 
STA 

PLYEV2 
LDY 
JSR 
JSR 
BCS 
DEC 
BEQ 
LDX 
LDY 
JSR 
BMI 

PLYOUT 



Y=A[0]+A[1]*X+A[2]*X**2+. . . +A[N]*X**N, N>0 

=[[■ - . [A[N]*X+A[N-1]]*X+. . .+A[2]]*X+A[1]]*X+A[0] 
INPUT: X IN FR0, N+l IN A-REG 
REG [X, Y]->A[N]. . .A[0] 
OUTPUT Y IN FR0 
USES FPTR2, PLYCNT, PLYARG 
CALLS FST0R, FMOVE, FLD1R, FADD, FMUL 
STX FPTR2 ;SAVE POINTER TO COEFF ' S 

FPTR2+1 
PLYCNT 

#PLYARG&$FF 

#PLYARG/$100 

FST0R ,-SAVE ARG 

FMOVE ;ARG->FR1 

FPTR2 

FPTR2+1 

FLD0R 

PLYCNT 

PLYOUT 
JSR FMUL 

PLYOUT 



FPTR2 

#FPREC 

FPTR2 

PLYEV2 

FPTR2+1 

#0 

FPTR2+1 

FPTR2 
FPTR2+1 
FLD1R 
FADD 
PLYOUT 
PLYCNT 
PLYOUT 
#PLYARG&$FF 
#PLYARG/?100 
FLD1R 
PLYEV1 



;COEF->FR0 [INIT SUM] 

DONE ? 
SUM * ARG 
' FLOW 

;BUMP COEF POINTER 



; ACROSS PAGE 



GET NEXT COEF 
SUM*ARG + COEF 
' FLOW 

rDONE ? 



;GET ARG AGAIN 
; [=JMP] 



Floating Load/Store 









* 


LOAD FR0 FROM [X,Y] 


X=LSB, Y=MSB, 


USES FLPTR [PG0] 


DD89 


86FC 




FLD0R 


STX FLPTR 


; SET FLPTR => 


[X,Y] 


DD8B 


84FD 




STY 


FLPTR+1 






DD8D 


A005 




FLD0P 


LDY #FPREC-1 


; # BYTES ENTER 


HERE W/FLPTR SET 


DD8F 


B1FC 




FLD01 


LDA [FLPTR], Y 


; MOVE 




DD91 


99D400 




STA 


FR0, Y 






DD94 


88 




DEY 








DD95 


10F8 * 


DD8F 


BPL 


FLD01 


; COUNT S, LOOP 




DD97 


60 




RTS 

* 
* 


LOAD FR1 FROM [X,Y] 


OR [FLPTR] 




DD98 


86FC 




FLD1R 


STX FLPTR 


; FLPTR=>[X,Y] 





267 



Source Code 



DD9A 


84FD 




STY 




FLPTR+1 


DD9C 


A005 




FLD1P 


LDY 


#FPREC-1 


DD9E 


B1FC 




FLD11 


LDA 


[FLPTR], Y 


DDA0 


99E000 




STA 




FR1, Y 


DDA3 


88 




DEY 






DDA4 


10F8 * 


DD9E 


BPL 




FLD11 


DDA6 


60 




RTS 












• 


STORE FR0 IN [X,Y 


DDA7 


86FC 




FST0R 


STX 


FLPTR 


DDA9 


84FD 




STY 




FLPTR+1 


DDAB 


A005 




FST0P 


LDY 


#FPREC-1 


DDAD 


B9D400 




FST01 


LDA 


FR0, Y 


DDB0 


91FC 




STA 




[FLPTR], Y 


DDB2 


88 




DEY 






DDB3 


10F8 " 


DDAD 


BPL 




FST01 


DDB5 


60 




RTS 







; # BYTES ENTER W/FLPTR SET 
; MOVE 



COUNT 5, LOOP 



ENTRY W/FLPTR SET 



MOVE FR0 TO FR1 



DDB6 






MV0TO1 






DDB6 


A205 




FMOVE 


LDX 


#FPREC-1 


DDB8 


B5D4 




FMOVE1 


LDA 


FR0.X 


DDBA 


95E0 




STA 




FR1.X 


DDBC 


CA 




DEX 






DDBD 


10F9 


*DDB8 


BPL 




FMOVE 1 


DDBF 


60 




RTS 







EXP[X] and EXP10[X] 



DDC0 


A289 


EXP 




LDX 


#LOG10ES.$FF 


; E**X = 10**[X*LOG10[E]] 


DDC2 


A0DE 




LDY 




#LOG10E/$100 




DDC4 


2098DD 




JSR 




FLD1R 




DDC7 


20DBDA 




JSR 




FMUL 




DDCA 


B07F "DE4B 




BCS 




EXPERR 




DDCC 


A900 


EXP 10 


LDA 


#0 


; 10**X 


DDCE 


85F1 




STA 




XFMFLG 


; CLEAR TRANSFORM FLAG 


DDD0 


A5D4 




LDA 




FR0 




DDD2 


85F0 




STA 




SGNFLG 


; REMEMBER ARG SGN 


DDD4 


297F 




AND 




#$7F 


; ; & MAKE PLUS 


DDD6 


85D4 




STA 




FR0 




DDD8 


38 




SEC 








DDD9 


E940 




SBC 




#?40 




DDDB 


3026 "DE03 




BMI 




EXP1 


; X<1 SO USE SERIES DIRECTLY 






* 




10**X = 10**[I+F] = 


[10**1] * [10**F] 


DDDD 


C904 




CMP 




#FPREC-2 




DDDF 


106A "DE4B 




BPL 




EXPERR 


; ARG TOO BIG 


DDE1 


A2E6 




LDX 




#FPSCR&$FF 




DDE 3 


A005 




LDY 




#FPSCR/$100 




DDE5 


20A7DD 




JSR 




FST0R 


; SAVE ARG 


DDE 8 


20D2D9 




JSR 




FPI 


; MAKE INTEGER 


DDEB 


A5D4 




LDA 




FR0 




DDED 


85F1 




STA 




XFMFLG 


; SAVE MULTIPLIER EXP IN XFORM 


DDEF 


A5D5 




LDA 




FR0+1 


; CHECK MSB 


DDF1 


D058 "DE4B 




BNE 




EXPERR 


; SHOULD HAVE NONE 


DDF3 


20AAD9 




JSR 




IFP 


; NOW TURN IT BACK TO FLPT 


DDF6 


20B6DD 




JSR 




FMOVE 




DDF9 


A2E6 




LDX 




#FPSCR&$FF 




DDFB 


A005 




LDY 




KFPSCR/S100 




DDFD 


2089DD 




JSR 




FLD0R 


; GET ARG BACK 


DE00 


2060DA 




JSR 




FSUB 


r ARG - INTEGER PART = FRACTIO 






* 




NOW 


HAVE FRACTION PART OF ARG [F] IN FR0, 






* 




INTEGER PART [I] 








* 




IN 


XFMFLG. USE SERIES APPROX FOR 






* 




10* 


*F, THEN MULTIPLY 


' BY 10**1 


DE03 




EXP1 








DE03 


A90A 




LDA 




SNPCOEF 




DE05 


A24D 




LDX 




#P10COF6,$FF 




DE07 


A0DE 




LDY 




#P10COF/$100 





268 



Source Code 



DE09 
DE0C 
DE0F 
DE12 
DE14 
DE16 
DE17 
DE17 
DE18 
DE1A 
DE1C 
DE1E 
DE20 
DE22 
DE24 
DE26 
DE28 
DE29 
DE2B 
DE2D 
DE2E 
DE30 
DE32 
DE34 
DE36 
DE39 
DE3B 
DE3D 
DE40 
DE42 
DE44 
DE47 
DE4A 
DE4B 
DE4C 
DE4D 

DE53 

DE59 

DE5F 

DE65 

DE6B 

DE71 

DE77 

DE7D 

DE83 

DE89 
DE8F 



~DE4B 
"DE4B 



2040DD 

20B6DD 

20DBDA 

A5F1 

F023 "DE39 

18 

+6A 
85E0 
A901 

9002 "DE20 
A910 
85E1 
A204 
A900 
95E2 
CA 

10FB "DE26 
A5E0 
18 

6940 
B019 
3017 
85E0 
20DBDA 
A5F0 

100D *DE4A 
20B6DD 
A28F 
A0DE 
2089DD 
2028DB 
60 
38 
60 

3D17941900 
00 

3D57330500 
00 

3E05547662 
00 

3E32196227 
00 

3F01686030 
36 

3F07320327 
41 

3F25433456 
75 

3F66273730 
50 

4001151292 
55 

3F99999999 
99 

= 000A 
3F43429448 
19 

4001000000 
00 



JSR 


PLYEVL 


JSR 


FMOVE 


JSR 


FMUL 


LDA 


XFMFLG 


BEQ 


EXPSGN 


CLC 




RORA 




ROR 


A 


STA 


FR1 


LDA 


#1 


BCC 


EXP2 


LDA 


#510 



EXP2 STA FR1+1 
LDX IFPREC-2 
LDA #0 

EXP3 STA FR1+2.X 
DEX 



BPL 
LDA 
CLC 
ADC 
BCS 
BMI 
STA 
JSR 
EXPSGN LDA 



EXP 3 
FR1 

#540 

EXPERR 

EXPERR 

FR1 

FMUL 

SGNFLG 



,-P[X] 

;P[X]*P[X] 

; DID WE TRANSFORM ARG 

,- NO SO LEAVE RESULT ALONE 

; 1/2 

; SAVE AS EXP-TO-BE 

; GET MANTISSA BYTE 

; CHECK BIT SHIFTED OUT OF A 

; I WAS ODD - MANTISSA = 10 



CLEAR REST OF MANTISSA 



BACK TO EXPONENT 

BIAS IT 

OOPS. . . IT'S TOO BIG 

FR1 = 10**1 
[10**IJ*[10**F: 
WAS ARG<0 
NO-DONE 
YES-INVERT RESULT 



BPL EXPOUT 

JSR FMOVE 

LDX #FONE&5FF 

LDY #FONE/5100 

JSR FLD0R 

JSR FDIV 

EXPOUT RTS 

EXPERR SEC 

RTS 

P10COF .BYTE 53D, 517, 594, 519,0,0 ; 0. 00001 79419 

.BYTE 53D, 557, 533, 505, 0, ,-0.0000573305 

.BYTE 53E, 505, 554, 576, 562,0 ; . 0005547662 

.BYTE 53E, 532, 519, 562, 527, ,- Z 

.BYTE 53F, 501, 568, 560,530,536 

.BYTE 53F, 507, 532, 503, 527, 541 

.BYTE 53F, 525, 543, 534,556,575 

.BYTE 53F, 566, 527, $37, 530, 550 

.BYTE 540,501,515,512,592,555 

.BYTE 53F, 599, 599, 599, 599, 599 



[PANT, PANT - FINISHED::] 
FLAG ERROR 
5, QUIT 



0032176227 

0.0168603036 

0.0732032741 

0.2543345675 

0.6627373050 

1.15129255 

0.999999999 



NPCOEF 
LOG10E 



EQU 
. BYTE 



(*-P10COF)/FPREC 

53F, 543, 542, $94, 548, 519 



LOG10[E] 



.BYTE 540,1,0,1 



Z a [X-C]/[X + C] 



DE95 


86FE 


XFORM STX FPTR2 


DE97 


84FF 


STY 


FPTR2+1 


DE99 


A2E0 


LDX 


#PLYARG£,5FF 


DE9B 


A005 


LDY 


#PLYARG/5100 


DE9D 


20A7DD 


JSR 


FST0R 


DEA0 


A6FE 


LDX 


FPTR2 


DEA2 


A4FF 


LDY 


FPTR2+1 



; STASH X IN PLYARG 



269 



Source Code 



DEA4 
DEA7 
DEAA 
DEAC 
DEAE 
DEB1 
DEB3 
DEB 5 
DEB8 
DEBA 
DEBC 
DEBF 
DEC 2 
DEC4 
DEC 6 
DEC 9 
DECC 



2098DD 

2066DA 

A2E6 

A005 

20A7DD 

A2E0 

A005 

2089DD 

A6FE 

A4FF 

2098DD 

2060DA 

A2E6 

A005 

2098DD 

2028DB 

60 



JSR 
JSR 
LDX 
LDY 
JSR 
LDX 
LDY 
JSR 
LDX 
LDY 
JSR 
JSR 
LDX 
LDY 
JSR 
JSR 
RTS 



FLD1R 

FADD 

#FPSCR6,$FF 

#FPSCR/$100 

FST0R 

#PLYARGS,$FF 

#PLYARG/$100 

FLD0R 

FPTR2 

FPTR2+1 

FLD1R 

FSUB 

#FPSCR5,$FF 

#FPSCR/$100 

FLD1R 

FDIV 



[X-C]/[X+C] = Z 



LOG10[X] 



DECD 


A901 


DECF 


D002 "I 


DED1 


A900 


DED3 


85F0 


DED5 


A5D4 


DED7 


1002 "I 


DED9 


38 


DEDA 


60 


DEDB 




DEDB 


A5D4 


DEDD 


85E0 


DEDF 


38 


DEE0 


E940 


DEE 2 




DEE 2 


+0A 


DEE 3 


85F1 


DEE5 


A5D5 


DEE 7 


29F0 


DEE 9 


D004 "I 


DEEB 


A901 


DEED 


D004 "I 


DEEF 


E6F1 


DEF1 


A910 


DEF3 


85E1 


DEF5 


A204 


DEF7 


A900 


DEF9 


95E2 


DEFB 


CA 


DEFC 


10FB "1 


DEFE 


2028DB 


DF01 




DF01 


A266 


DF03 


A0DF 


DF05 


2095DE 


DF08 


A2E6 


DF0A 


A005 


DF0C 


20A7DD 


DF0F 


20B6DD 


DF12 


20DBDA 


DF15 


A90A 


DF17 


A272 


DF19 


A0DF 


DF1B 


2040DD 


DF1E 


A2E6 


DF20 


A005 


DF22 


2098DD 



LOG LDA # 1 
BNE LOGBTH 

LOG10 LDA #0 

LOGBTH STA SGNFLG 



; REMEMBER ENTRY POINT 

; CLEAR FLAG 

; USE SGNFLG FOR LOG/LOG10 
MARKER 



LDA 


FR0 


BPL 


LOG 5 


LOGERR 


SEC 


RTS 




LOG 5 





WE WANT X 

10**Y HAS SAME EXP 

S, MANTISSA BYTE 



F*[10**Y], 1<F<10 
BYTE AS X 
1 OR 10 



LDA 



FRO 



STA 




FR1 




SEC 








SBC 




#$40 




AS LA 








ASL 




A 




STA 




XFMFLG 


; REMEMBER Y 


LDA 




FR0+1 




AND 




#$F0 




BNE 




LOG 2 




LDA 




#1 




BNE 




LOG 3 




LOG 2 


INC 


XFMFLG 


; BUMP Y 


LDA 




#$10 




LOG3 


STA 


FR1+1 


; SET UP MANTISSA 


LDX 




#FPREC-2 


; CLEAR REST OF MANTIS 


LDA 




#0 




LOG4 


STA 


FR1+2.X 




DEX 








BPL 




LOG 4 




JSR 




FDIV 


; X = X/tl0**Y] - S.B. 
IN [1, 10] 


FLOG10 






; ;LOG10[X], 1<=X<=10 


LDX 




#SQR10&$FF 




LDY 




#SQR10/$100 




JSR 




XFORM 


,-Z = [X-C]/[X+C],C*C = 


LDX 




#FPSCR&$FF 




LDY 




#FPSCR/$100 




JSR 




FST0R 


;SAVE Z 


JSR 




FMOVE 




JSR 




FMUL 


; Z*Z 


LDA 




#NLCOEF 




LDX 




#LGCOEPS,$FF 




LDY 




#LGCOEF/$100 




JSR 




PLYEVL 


; P[Z*Z] 


LDX 




#FPSCR£.$FF 




LDY 




#FPSCR/$100 




JSR 




FLD1R 





270 



Source Code 



*) 



DF25 
DF28 
DF2A 
DF2C 
DF2F 
DF32 
DF35 
DF37 
DF39 
DF3B 
DF3D 
DF3F 
DF41 
DF42 
DF44 
DF46 
DF46 
DF49 
DF4B 
DF4D 
DF4F 
DF51 
DF53 
DF53 
DF56 
DF56 
DF58 
DF5A 
DF5C 
DF5E 
DF61 
DF64 
DF65 
DF66 

DF6C 

DF72 

DF78 

DF7E 

DF84 

DF8A 

DF90 

DF96 

DF9C 

DFA2 

DFA8 

DFAE 
DFB4 
DFBA 
DFC0 
DFC6 
DFCC 
DFD2 



20DBDA 

A26C 

A0DF 

2098DD 

2066DA 

20B6DD 

A900 

85D5 

A5F1 

85D4 

1007 "DF46 

49FF 

18 

6901 

85D4 

20AAD9 

24F1 

1006 "DF53 

A980 

05D4 

85D4 

2066DA 

A5F0 

F00A "DF64 

A289 

A0DE 

2098DD 

2028DB 

18 

60 

4003162277 

66 

3F50000000 

00 

3F49155711 

08 

BF51704947 

08 

3F39205761 

95 

BF04396303 

55 

3F10093012 

64 

3F09390804 

60 

3F12425847 

42 

3F17371206 

08 

3F28952971 

17 

3F86858896 

44 

= 000A 

3E16054449 

00 

BE95683845 

00 

3F02687994 

16 

BF04927890 

80 

3F07031520 

00 

BF08922912 

44 

3F11084009 

11 



JSR 

LDX 

LDY 

JSR 

JSR 

JSR 

LDA 

STA 

LDA 

STA 

BPL 

EOR 

CLC 

ADC 

STA 
LOG 6 

JSR 

BIT 

BPL 

LDA 

ORA 

STA 
LOG 7 

JSR 
LOGOUT 

LDA 

BEQ 

LDX 

LDY 

JSR 

JSR 
LOGDON CLC 

RTS 
SQR10 .BYTE 



FMUL 

#FHALF£,$FF 

#FHALF/$100 

FLD1R 

FADD 

FMOVE 

#0 

FR0+1 

XFMFLG 

FR0 

LOG6 

#-1 

#1 
FR0 

IFP 

XFMFLG 

LOG7 

#580 

FR0 

FR0 

FADD 

SGNFLG 

LOGDON 

SLOG10E&255 

#LOG10E/?100 

FLD1R 

FDIV 



; Z*P[Z*Z] 



0.5 + Z*P[Z*Z] 



FLIP SIGN 



LEAVES FR1 ALONE 



FLIP AGAIN 



LOG[X] = LOG[X] +Y 



,-WAS LOG10, NOT LOG 
; LOG[X]/LOG10[E] 



$40, $03, $16, $22, $77, $66 ;SQUARE ROOT OF 10 
FHALF .BYTE ?3F, $50, 0, 0, 0, ; 0.5 
LGCOEF .BYTE $3F , $49 , $1 5 , $5 7 , $1 1 , $08 ; . 4915571108 



.BYTE $BF, $51, $70, $49, $47, $08 

.BYTE $3F, $39, $20, $57, $61, $95 

.BYTE $BF, $04, $39, $63, $03, $55 

.BYTE $3F, $10, $09, $30, $12, $64 

.BYTE $3F, $09, $39, $08, $04, $60 

.BYTE $3F, $12, $42, $58, $47, $42 

.BYTE $3F, $17, $37, $12, $06, $08 

.BYTE ?3F, $28, $95, $29, $71, $17 
.BYTE 



-0.5170494708 
J. 3920576195 
-0.0439630355 
3. 1009301264 

| 0.0939080460 
). 1242584742 

; 0.1737120608 
(.28957117 



$3F, $86, $8 5, $88, $96, $44 ; . 8685889644 



NLCOEF EQU 
ATCOEF .BYTE 



(*-LGCOEF)/FPREC 
$3E, $16, $05, $44, $49, ( 



0016054449 

.BYTE $BE, $95, $68, $38, $45,0 ; -0 . 009568345 

.BYTE $3F, $02, $68, $79, $94, $16 ; . 0268799416 

.BYTE $BF, $04, $92, $78, $90, $80 ; -0 . 0492789080 

.BYTE $3F, $07, $03, $15, $20, ; . 07031 52000 

.BYTE $BF, $08, $92, $29, $12, $44 ; -0 . 0892291 244 

.BYTE $3F, $11, $08, $40, $09, $11 ; 0. 1 10840091 1 



271 






Source Code 



.BYTE $BF, $14, $28, $31, 556, $04 ,--0.1428315604 
.BYTE $3F, $19, $99, $98, $77, $44 ,-0.1999987744 
.BYTE $BF, $33, $33, $33, $31, $13 ; -0.3333333113 



DFD8 BF14283156 

04 
DFDE 3F19999877 

44 
DFE4 BF33333331 

13 
DFEA 3F99999999 FP9S .BYTE $3F, $99, $99 , $99, $99 , $99 ; 0.999999999 

99 

= 000B NATCF EQU ( *-ATCOEF) /FPREC 
DFF0 3F78539816 PI0V4 .BYTE $3F, $78 , $53, $98, $16, $34 ,- Pi/4 = ARCTAN[1.0] 

34 



Atari Cartridge Vectors 



DFF6 


= BFF9 


ORG 


CRTGI 


BFF9 




SCVECT 




BFF9 


60 


RTS 




BFFA 


00A0 


DW 


COLDS 


BFFC 


00 


DB 





BFFD 


05 


DB 


5 


BFFE 


F9BF 


DW 


SCVEC 



; COLDSTART ADDR 
; CART EXISTS 
; FLAG 
COLDSTART ENTRY ADDR 



C000 



End of BASIC 



272 



Appendix A 



Macros in 
Source Code 



The following is a listing of the macros used in this source listing. You will 
be able to tell when a macro was used by a plus ( + ) sign to the left of the hex 
code produced in column two by the assembler. 



ASLA: MACRO 

%L ASL A 

ENDM 
RORA: MACRO 
%L ROR A 

ENDM 
LSRA: MACRO 
%L LSR A 

ENDM 
ROLA: MACRO 
%L ROL A 

ENDM 
FDB: MACRO 
%L DW REV (%1) 

IF '=%2' <> '=' 

DW REV (%2) 

IF l =%3 ' <> 

DW REV (%3) 

IF '=14' <> '=' 

DW REV (%4) 

IF '=S5 <> '=' 

DW REV (%5) 

ENDIF 

ENDIF 

ENDIF 

ENDIF 

ENDM 
LOCAL: MACRO 

PROC 

ENDM 
BYTE: MACRO 

IF '%1 ' = '=' 
%L DB $80+( ( (%2-*)S,?7F) XOR $40 ) 

ELSE 

IF '%!' = '08' 
%L DW ( %2 ) 

ELSE 
%L DB %1 

ENDIF 

ENDIF 

ENDM 



Syntax Table Macro 



THIS MACRO IS USED TO SIMULATE THE ACTION OF THE ORIGINAL 
ASSEMBLER IN HANDLING SPECIAL SYNTAX TABLE PSEUDO OPS AND 
OPERANDS 

THE 'SYN' MACRO EXAMINES UP TO 4 ARGUMENTS FOR CERTAIN SPECIAL 
CASE NAMES. 

IF THE NAME 'JS' IS FOUND, IT GENERATES A SPECIAL 'RELATIVE 
SYNTAX JSR' TO THE LABEL FOUND IN THE NEXT PARAMETER 



273 



Appendix A 



; IF THE NAME 'AD' IS FOUND, IT GENERATES A WORD ADDRESS OF 
; THE LABEL FOUND IN THE NEXT PARAMETER 

; ANY OTHER NAME IS ASSUMED TO BE A SIMPLE BYTE VALUE 

SYN: MACRO 

:SYAR2 SET '=«%2'<>' = ' 

:SYAR3 SET '=%3 '<>'=' 

:SYAR4 SET '=%4 '<>'=' 

IF '%1' = 'JS' 

%L DB $80+( ( (»2-*)&$7F) XOR $40 ) 

:SYAR2 SET 

ELSE 

IF '%1' = 'AD' 

%L DW (%2) 

:SYAR2 SET 

ELSE 

%L DB %1 
ENDIF 

ENDIF 

IF :SYAR2 

IF '%2' = 'JS' 

DB $80+( ( (%3-*)&$7F) XOR $40 ) 
:SYAR3 SET 
ELSE 

IF '%2' = 'AD' 
DW (%3) 
:SYAR3 SET 
ELSE 

DB %2 
ENDIF 
ENDIF 
ENDIF 

IF :SYAR3 

IF ' %3 ' = ' JS ' 

DB $80+( ( (%4-*)&?7F) XOR $40 ) 
:SYAR4 SET 
ELSE 

IF '%3' = 'AD' 
DW (%4) 
:SYAR4 SET 
ELSE 

DB %3 
ENDIF 
ENDIF 
ENDIF 

IF :SYAR4 

IF '%4' = 'JS' 

DB $80+( ( (%5-*)&$7F) XOR $40 ) 

ELSE 

IF '%4' = 'AD' 

DW (%5) 

ELSE 

DB %4 

ENDIF 
ENDIF 
ENDIF 

ENDM 



274 



Appendix B 



The Bugs in 
Atari BASIC 



Yes, it's true. There are some bugs in Atari BASIC. Of course, 
that's not surprising, since Atari released the product as ROM 
without giving the authors a chance to do second-round bug- 
fixing. But what hurts, a little, is that most of the fixes for the 
bugs have been known since June of 1979. 

As this book is being written, rumor has it that at last Atari 
is in the final stages of releasing a new version of the BASIC 
ROMs. Unfortunately, these modified ROMs will appear too 
late for us to comment upon them in this edition. On the other 
hand, there are supposed to be fewer than twenty fixes 
implemented (which isn't a bad record for a product as mature 
as Atari BASIC), so those of you who are willing to PEEK 
around a bit can use this listing as at least a road map to the 
new ROMs. 

In any case, though, we thought it would be appropriate to 
mention a few of the bugs we know about, show you why they 
exist, and tell how we fixed them back there in the summer of 
'79. 

The Editing and String Bug 

In the course of editing a BASIC program, sometimes the 
system loses all or part of the program, or it simply hangs. 
Often, even SYSTEM RESET will not return control to the user. 

Also, string assignments that involve the movement of 
exact multiples of 256 bytes do not move the bytes properly. 
For example, A$ = B$(257,512) would actually move bytes 513 
through 768 of B$ into bytes 257 through 512 of A$, even if 
neither string were DIMensioned to those values. 

Both of these are really the same bug. And both are caused 
because we strove to be a little too efficient. 

There are many ways to move strings of bytes using the 
6502's instruction set. The simplest and most-used methods, 
though, are excruciatingly slow. So Paul and Kathleen 
invented a super-fast set of move-memory routines, one for 



275 



Appendix B 



moving up in memory (EXPAND, at $A881) and one for 
moving down in memory (CONTRACT, at $A8FD). 
Unfortunately, the routines are very complex (which is what 
makes them fast) and difficult to interface with properly. And 
so a bug crept into CONTRACT. 

Take a look at the code of FMOVER ($A947). When we get 
here, we expect MVLNG to contain the complement of the least 
significant byte of the move length while MVLNG + 1 contains 
its most significant byte. But look what happens if the original 
move length was, for example, $200. The complement of the 
least significant byte ($00) is still zero ($00), so the BEQ to 
:CONT4 occurs immediately. 

But by then, the X register contains the number of pages to 
move plus one (X would contain 3 in this example), so we 
increment it (it becomes 2) and go to label :CONT3, where we 
bump the high-order byte of both the source and destination 
addresses. Ah, but therein lies the rub! We haven't yet done 
anything with the first values in those source and destination 
addresses, so we have effectively skipped 256 bytes of each! 

The solution is to replace the BEQ :CONT4 at $A94E with 
the following code: 

DEX 

BNE :CONT2 
RTS 

Do you see the difference? If we enter with MVLNG equal 
to zero, we immediately move 256 bytes (at :CONT2) before ever 
attempting to change the source and destination addresses. 

And this fix works, honest. We've been using it like this for 
over two years in BASIC A + . 

Minus Zero 

Taking the unary minus of a number (A = : PRINT -A) can 
result in garbage. Usually, this garbage will not affect 
subsequent calculations, but it does print strangely. And how 
did this come about? 

We simply forgot to take into consideration the fact that 
zero doesn't really have a sign. Look at the code for the unary 
minus operator (XPUMINUS, at $ACA8). Do you see the 
problem? We simply invert the most significant bit (the sign bit) 
of the floating point number in FRO. 



276 



Appendix B 



What we should have coded would be something like this: 

LDA FRO 
BEQ :NOINVERT 
EOR #$80 
STA FRO 
:NOINVERT 

Luckily, this is not too severe a problem to the BASIC user 
(one can always use "PRINT 0-A" instead of "PRINT -A"), 
but just think — it only cost two bytes to fix this bug. 

LOCATE and GET 

The GET statement does not reinitialize its buffer pointer, so it 
can do nasty things to memory if used directly after a statement 
which has changed the system buffer pointer. For example, 
GET can change the line number of a DATA statement if it is 
used after a READ. Also, the same problem exists for the 
LOCATE statement, since it calls GET. 

From BASIC, the easiest solution is to use a function or 
statement which is known to reset the pointer. Coding 
"XX = STR$(0)" works just fine, as does PRINTing any 
number. 

Within the source listing, the problem exists at location 
$BC82, label GET1. If the code had simply read as follows, 
there would be no bug: 

GET1 

JSR INTLBF ; reset buffer pointer 
LDA #ICGTC ; continue as before 

INPUT and READ 

Using either an INPUT or READ statement without a following 
variable does not cause a syntax error (as it should). Then, 
attempting to execute a statement such as 20 INPUT can cause 
total system lock-up. 

The solution from BASIC? Be careful and don't do it. 

And this is one bug that we will not show the fix for, 
simply because it's too long and involved. We will, however, 
point to labels :SINPUT and :SREAD (at locations $A6F4 and 
$A6F5) in the Syntax Tables and show why the bug exists. 

Note that the :SINPUT does a syntax call (SYN JS,) to the 
:OPD syntax, which looks for — but does not insist upon — a 
file number specifier (# < numeric expression > ). Then the 



277 



Appendix B 



syntax joins with :SREAD, which looks for zero or more 
variables. 

Oops! Zero or more? Shouldn't that be one or more? That's 
where the problem lies. 

Do Not Use NOT 

In all too many cases, the use of the NOT operator is 
guaranteed to get you in trouble. If you don't believe it, try 
this: PRINT NOT NOT 1. 

The explanation of why the bug occurs is too lengthy to 
give in detail here; suffice it to say that the precedence of NOT 
is wrong. Remember the Operator Precedence Table we 
displayed in Chapter 8 of Part 2? Look at what you got for the 
go-onto-stack and come-off-stack precedence values for NOT. 

Or look at location $ AC57, the NOT entry in OPRTAB . 
NOT uses a 7 for both its precedence values. But wait a minute. 
If two operators have the same apparent precedence (as in 
NOT NOT A or even A + B + C), the expression executor will 
pop the first one off the stack and execute it. But with a unary 
operator, there is nothing to execute yet. 

And the same bug exists for both unary minus and unary 
plus, so - -3 and + +5 don't execute properly. Of course, since 
unary plus doesn't really do anything, it doesn't matter. In the 
case of unary minus, though, all but the last minus sign in a 
string of minus signs is ignored (that is, - -3 produces -3 as a 
result, instead of +3, as it should). But, by an incredible 
coincidence, the damage that unary minus causes is invisible to 
Execute Expression as a whole and only produces the error 
noted. 

The fix? Well, if we want to leave NOT where it is in the 
order of things, the only way is to restructure the whole 
precedence table. But if we are willing to accord it a very high 
precedence, like unary plus and minus, we can fix it — and 
plus and minus — by changing the bytes at $AC57, $AC64, and 
$AC65 to $DC. And, thanks to the differing go-onto-stack and 
come-off-stack values, we can stack as many NOTs, pluses, or 
minuses as we want. 

Are these all the bugs we know about that can be fixed 
easily? No. But these are the easiest to understand or the 
easiest to fix, and we thought they were instructive. 

Of course, unless you have an EPROM board and burner 
handy, you may not be able to take advantage of these fixes. 



278 



Appendix B 



But at least now you may be able to work around them as you 
program with good old buggy-version Atari BASIC. 

And take heart. Remember Richard's Rule: Any nontrivial 
piece of software has bugs in it. And the corollary: Any piece of 
software which is bug-free is trivial. 



279 



Appendix C 



Labels and 

Hexadecimal 

Addresses 



AADD 


AF52 


CGTO 


0017 


CVFPI 


AD56 


EXEXPR 


AAE0 


AAPSTR 


AB98 


CI LET 


0036 


CVIFP 


D9AA 


EXOPOP 


AB0B 


n ADC 


AF53 


CIO 


E456 


DATAD 


00B6 


EXP 


DDC0 


ADFLAG 


00B1 


CIX 


00F2 


DATALN 


00B7 


EXP1 


DE03 


n AFP 


D800 


CLALL1 


BD4F 


n DCBORG 


0300 


EXP10 


DDCC 


AMUL1 


AF5D 


CLE 


001D 


DEGFLG 


00FB 


EXP2 


DE20 


AMUL2 


AF46 


CLEN 


0042 


DEGON 


0006 


EXP 3 


DE26 


APHM 


000E 


CLIST 


0004 


DIGRT 


00F1 


EXPAND 


A881 


ARGOPS 


0080 


CLPRN 


002B 


DIRFLG 


00A6 


EXPERR 


DE4B 


ARGP2 


AC06 


CLSALL 


BD41 


DNERR 


BCB0 


EXPINT 


AB2E 


ARGPOP 


ABF2 


CLSYS1 


BCF1 


DOSLOC 


000A 


EXPLOW 


A87F 


ARGPUS 


ABBA 


CLSYSD 


BCF1 


DSPFLG 


02FE 


EXPOUT 


DE4A 


ARGSTK 


0080 


CLT 


0020 


ECSIZE 


00A4 


EXPSGN 


DE39 


ARSLVL 


00AA 


CMINUS 


0026 


EEXP 


00ED 


EXSVOP 


00AB 


ARSTKX 


00AA 


CMUL 


0024 


ELADVC 


BADD 


EXSVPR 


00AC 


n ASCIN 


D800 


CNE 


001E 


ENDSTA 


008E 


FADD 


DA66 


ASLA 


mac 


CNFNP 


0044 


ENDVVT 


0088 


n FASC 


D8E6 


ATAN 


BE77 


CNOT 


0028 


ENTDTD 


00B4 


FBODY 


000C 


ATAN1 


BE9A 


COLD1 


A008 


EPCHAR 


005D 


FCHRFL 


00F0 


ATAN 2 


BED4 


COLDST 


A000 


ERBRTN 


B920 


FDB 


mac 


ATCOEF 


DFAE 


COLOR 


00C8 


ERGFDE 


B922 


FDIV 


DB28 


ATEMP 


00AF 


COMCNT 


00B0 


ERLTL 


B924 


FHALF 


DF6C 


ATNOUT 


BEE2 


CON 


001E 


ERNOFO 


B926 


FIXRST 


B825 


BININT 


00D4 


CONTLO 


A8FB 


ERNOLN 


B928 


FLD01 


DD8F 


BOTH 


BDB3 


CONTRA 


A8FD 


n ERON 


B93E 


n FLD0P 


DD8D 


BRKBYT 


0011 


COPEN 


BBB6 


EROVFL 


B92A 


FLD0R 


DD89 


BYELOC 


E471 


COR 


0029 


ERRAOS 


B92C 


FLD11 


DD9E 


n BYTE 


mac 


COS 


BDB1 


ERRDIM 


B92E 


n FLD1P 


DD9C 


C 


0044 


COX 


0094 


ERRDNO 


B918 


FLD1R 


DD98 


BYELOC 


E471 


CPC 


009D 


ERRINP 


B930 


FLIM 


0000 


n BYTE 


mac 


CPLUS 


0025 


ERRLN 


B932 


FLIST 


BAD5 


C 


0044 


CPND 


001C 


ERRNSF 


B916 


n FLOG10 


DF01 


CAASN 


002D 


CR 


009B 


ERRNUM 


00B9 


FLPTR 


00FC 


CACOM 


003C 


CREAD 


0022 


ERROOD 


B934 


FMOVE 


DDB6 


CADR 


0043 


CREGS 


02C4 


ERROR 


B940 


FMOVE1 


DDB8 


CALPRN 


0038 


CRPRN 


002C 


ERRPTL 


B91A 


FMOVER 


A947 


CAND 


002A 


CRTGI 


BFF9 


ERRSAV 


00C3 


FMPREC 


0005 


CASC 


0040 


CSASN 


002E 


ERRSSL 


B936 


FMUL 


DADB 


CCHR 


003E 


CSC 


0015 


ERRVSF 


B938 


n FNTAB 


A829 


CCOM 


0012 


CSEQ 


0034 


ERSVAL 


B91C 


FONE 


DE8F 


CCR 


0016 


CSGE 


0031 


ERVAL 


B93A 


FP9S 


DFEA 


CDATA 


0001 


CSGT 


0033 


ESIGN 


00EF 


FPI 


D9D2 


CDIV 


0027 


CSLE 


002F 


EVAADR 


0002 


FPONE 


BE71 


CDLPRN 


0039 


CSLPRN 


0037 


EVAD1 


0004 


FPORG 


D800 


n CDOL 


0013 


CSLT 


0032 


EVAD2 


0006 


FPREC 


0006 


n CDQ 


0010 


CSNE 


0030 


n EVARRA 


0040 


FPSCR 


05E6 


CDSLPR 


003B 


CSOE 


0011 


EVDIM 


0001 


FPSCR1 


05EC 


CEOS 


0014 


CSROP 


001D 


n EVNUM 


0001 


FPTR2 


00FE 


CEQ 


0022 


CSTEP 


001A 


EVSADR 


0002 


FR0 


00D4 


CERR 


0037 


CSTR 


003D 


EVSCAL 


0000 


FR0M 


00D5 


CEXP 


0023 


CTHEN 


001B 


EVSDIM 


0006 


FR1 


00E0 


CFFUN 


003D 


CTO 


0019 


EVSDTA 


0002 


FR1M 


00E1 


CFLPRN 


003A 


CUMINU 


0036 


EVSLEN 


0004 


FR2 


00E6 


CFOR 


0008 


CUPLUS 


0035 


EVSTR 


0080 


FRA10 


DD01 


CGE 


001F 


CUSR 


00 3 F 


n EVTYPE 


0000 


FRA1E 


DD09 


CGOSUB 


000C 


CVAFP 


D800 


n EWALU 


0002 


FRA20 


DD05 


CGS 


0018 


CVAL 


0041 


EXECNL 


A95F 


FRA2E 


DD0F 


CGT 


0021 


CVFASC 


D8E6 


EXECNS 


A962 


FRADD 


AD3B 



281 



Appendix C 



FRCMP 


AD35 


FRCMPP 


AD32 


FRDIV 


AD4D 


FRE 


00DA 


FRMUL 


AD47 


FRSIGN 


00EE 


FRSUB 


AD41 


FRUN 


BAF7 


FRX 


00EC 


FSCR 


05E6 


FSCR1 


05EC 


FSQR 


BF08 


FST01 


DDAD 


n FST0P 


DDAB 


FST0R 


DDA7 


FSTEP 


0006 


FSUB 


DA60 


FTWO 


BF93 


GDIOl 


BC22 


GDVCIO 


BC1D 


GET1 


BC82 


GET1IN 


ABE9 


GETINT 


ABE0 


GETLL 


A9DD 


n GETPI0 


ABD8 


GETPIN 


ABD5 


GETSTM 


A9A2 


GETTOK 


AB3E 


GETVAR 


AB89 


GFDISP 


0003 


GFHEAD 


0004 


n GFLNO 


0001 


GFTYPE 


0000 


GIOCMD 


BD04 


GIODVC 


BC9F 


GIOPRM 


BD02 


GLGO 


BA92 


GLINE 


BA89 


GLPCX 


BAC4 


GLPX 


BAC6 


n GNLINE 


BA80 


GNXTL 


A9D0 


GRFBAS 


0270 


GSTRAD 


AB9B 


GTINTO 


ABE3 


GWTAD 


AC28 


HIMEM 


02E5 


HMADR 


02E5 


n IBUFFX 


00A9 


ICAUX1 


034A 


ICAUX2 


034B 


ICAUX3 


034C 


ICAUX4 


034D 


ICAUX5 


034E 


ICBAH 


0345 


ICBAL 


0344 


ICBLH 


0349 


ICBLL 


0348 


ICCLOS 


000C 


ICCOM 


0342 


n ICDDC 


000E 


n ICDNO 


0341 


I C DRAW 


0011 


n ICFREE 


00FF 


a ICGBC 


0006 


n ICGBR 


0004 


ICGR 


001C 


ICGTC 


0007 


ICGTR 


0005 


n ICHID 


0340 


ICLEN 


0010 


n ICMAX 


000E 



n 


ICOIN 


0001 




ICOIO 


0003 


n 


ICOOUT 


0002 


n 


ICPBC 


000A 


n 


ICPBR 


0008 




ICPTC 


000B 


n 


ICPTR 


0009 




ICPUT 


0346 




ICSBRK 


0080 


n 


ICSDER 


0083 


n 


ICSDNR 


0081 


n 


ICSEOF 


0003 


n 


ICSIVC 


0084 


n 


ICSIVN 


0086 


n 


ICSNED 


0082 


n 


ICSNOP 


0085 


n 


ICSOK 


0001 




ICSTA 


0343 




ICSTAT 


000D 


n 


ICSTR 


0002 


n 


ICSWPE 


0087 




IFP 


D9AA 


n 


ILSHFT 


DA 5 A 




INBUFF 


00F3 




INDEX2 


0097 




INTLBF 


DA51 




101 


BD0A 


n 


102 


BD0E 




103 


BD10 




104 


BD12 




105 


BD19 


n 


106 


BD1D 




107 


BD24 




108 


BD26 




IOCB 


0340 




IOCBOR 


0340 




IOCMD 


00C0 




IODVC 


00C1 




I0TES2 


BCB6 




IOTEST 


BCB3 




ISVAR 


BD2F 




ISVAR1 


BD2D 


ii 


LBPR1 


057E 


n 


LBPR2 


057F 




LBUFF 


0580 




LDDVX 


BCA6 




LDIOST 


BCFB 




LDLINE 


B578 




LELNUM 


00AD 




LGCOEF 


DF72 




LISTDT 


00B5 




LLINE 


B55C 




LLNGTH 


009F 




LMADR 


02E7 




LOADFL 


00CA 




LOCAL 


mac 




LOG 


DECD 


n 


L0G1 


DEDB 




LOG10 


DED1 




LOG10E 


DE89 




L0G2 


DEEF 




LOG 3 


DEF3 




L0G4 


DEF9 




LOG 5 


DEDB 




L0G6 


DF46 




LOG 7 


DF53 




LOGBTI] 


DED3 




LOGDOK 


DF64 


r 


i LOGERF 


. DED9 


r 


i LOGOUT 


DF56 




LOMEM 


0080 




LPRTOP 


: B535 



LSRA 


mac 


RNDDIV 


B0A8 


LSTMC 


B63D 


RNDLOC 


D20A 


MAXC I X 


009F 


ROLA 


mac 


MDEND 


DB1A 


ROM 


A000 


MDESUP 


DCCF 


RORA 


mac 


MDSUP 


DCE0 


RSHF0E 


DC62 


MEMFUL 


B93C 


RSHFT0 


DC 3 A 


MEMTOP 


0090 


RSHFT1 


DC3E 


n MEND1 


DB1E 


RSTPTR 


B8AF 


MEND2 


DB21 


RSTSEO 


BD99 


MEND3 


DB24 


RTNVAR 


AC16 


MEOLFL 


0092 


RUNINI 


B8F8 


MISCR1 


0480 


RUNSTK 


008E 


MISCRA 


0500 


SAVCUR 


00BE 


MV0TO1 


DDB6 


SAVDEX 


00B3 


MVFA 


0099 


SCANT 


00AF 


MVFR0E 


DD34 


SCOEF 


BE41 


MVFR12 


DD28 


SCRX 


0055 


MVLNG 


00A2 


SCRY 


0054 


MVTA 


009B 


SCVECT 


BFF9 


NATCF 


000B 


SEARCH 


A462 


NCTOFR 


AB4D 


SETDZ 


BD72 


NIBSH0 


DBEB 


SETLIN 


B818 


NIBSH2 


DBE7 


SETLN1 


B81B 


NLCOEF 


000A 


SETSEO 


BD79 


NOCD0 


BD01 


SGNFLG 


00F0 


NORM 


DC00 


SICKIO 


BCB9 


N0RM1 


DC04 


SIN 


BDA7 


NPCOEF 


000A 


SINDON 


BE40 


NSCF 


0006 


SINERR 


BDA5 


NSIGN 


00EE 


SINF1 


BDF6 


NXTSTD 


00A7 


SINF3 


BE00 


ONLOOP 


00B3 


SINF4 


BE11 


OPETAB 


AA70 


SINF5 


BDE4 


OPNTAB 


A7E3 


n SINF6 


BDD5 


OPRTAB 


AC3F 


SINF7 


BDCC 


OPSTKX 


00A9 


n SINOVF 


BDCB 


OUTBUF 


0080 


SIX 


0480 


P10COF 


DE4D 


SKBLAN 


DBA1 


n PATCH 


BDA4 


SKCTL 


D20F 


PATS I Z 


0001 


SKPBLA 


DBA1 


PI0V18 


BE6B 


SNTAB 


A4AF 


PI0V2 


BE5F 


SNX1 


A050 


PI0V4 


DFF0 


SNX2 


A053 


PLYARG 


05E0 


SNX3 


A05D 


PLYCNT 


00EF 


SOPEN 


BBD1 


PLYEV1 


DD5B 


SOX 


0481 


PLYEV2 


DD6F 


SPC 


0482 


PLYEVL 


DD40 


SQR 


BEE5 


PLYOUT 


DD88 


SQR1 


BF00 


POKADR 


0095 


SQR10 


DF66 


P0P1 


AC0F 


SQR2 


BF84 


POPRST 


B841 


SQR3 


BF8A 


PRCHAR 


BA9F 


SQRCNT 


00EF 


PRCR 


BD6E 


SQRDON 


BF64 


PRCX 


BAA1 


SQRERR 


BEE3 


PRDY1 


BD59 


SQRLP 


BF2A 


PREADY 


BD57 


SQROUT 


BF92 


PROMPT 


00C2 


SRCADR 


0095 


PSHRST 


B683 


SRCNXT 


A490 


PSTR 


B480 


SRCSKP 


00AA 


PTABW 


00C9 


SREG1 


D208 


PUTCHA 


BA9F 


SREG2 


D200 


QTEMP 


00D9 


SREG3 


D201 


RADFLG 


00FB 


SSTR 


BA73 


RADON 


0000 


STACK 


0480 


RESCUR 


B6BE 


STARP 


008C 


RISASN 


AEA6 


STENUM 


00AF 


RISC 


AB64 


STETAB 


AA00 


RML 


0007 


STINDE 


00A8 


RMSG 


BD67 


STKLVL 


00A9 






STMCUR 


008A 



282 



Appendix C 



STMLBD 


00A7 


STMSTR 


00A8 


STMTAB 


0088 


STOP 


B7A7 


STOPLN 


00BA 


STRCMP 


AF81 


SVCOLO 


02FB 


SVDISP 


00B2 


SVESA 


0097 


SVONTC 


00B0 


SVONTL 


00B2 


SVONTX 


00B3 


SWNTP 


00AD 


SWVTE 


00B1 


SYN 


mac 


SYNTAX 


A060 


TEMPA 


00C4 


TENDST 


A9E2 


n TESTRT 


A9E7 


TOPRST 


0090 


TRAPLN 


00BC 


TSCOX 


00AB 


TSLNUM 


00A0 


TSTALP 


A3F7 


TSTBRK 


A9F4 


TSTEND 


B910 


TSTNUM 


DBAF 


TVNUM 


00D3 


TVSCIX 


00AC 


TVTYPE 


00D2 


VNTD 


0084 


VNTP 


0082 


VNUM 


00D3 


VTYPE 


00D2 


WTP 


0086 


WARMFL 


0008 


WARMST 


A04D 


WWTPT 


009D 


XBYE 


A9E8 


XCLOAD 


BBAC 


XCLOSE 


BC1B 


XCLR 


B766 


XCMP 


AD26 


XCOLOR 


BA29 


XCOM 


B1D9 


XCONT 


B7BE 


XCSAVE 


BBA4 



XDATA 


A9E7 


XPCHR 


B067 


XDEG 


B261 


XPCOS 


B125 


XDIM 


B1D9 


XPDIV 


AC9F 


XDOS 


A9EE 


XPDLPR 


AD82 


XDPSLP 


AD82 


XPEQ 


AC DC 


XDRAWT 


BA31 


XPEXP 


B14D 


XEND 


B78D 


XPFLPR 


AD7B 


XENTER 


BACB 


XPFRE 


AFEB 


XERR 


B91E 


XPGE 


ACD5 


XFALSE 


AD00 


XPGT 


ACCC 


XFMFLG 


00F1 


XPIFP 


AFD1 


XFOR 


B64B 


XPIFP1 


AFD5 


XFORM 


DE95 


XPIFP2 


AFD8 


XGET 


BC7F 


XPINT 


B0DD 


XGOl 


B6AE 


XPL10 


B143 


XG02 


B6A6 


XPLE 


ACB5 


XGOSUB 


B6A0 


XPLEN 


AFCA 


XGOTO 


B6A3 


XPLOG 


B139 


XGR 


BA50 


XPLOT 


BA76 


XGS 


B6C7 


XPLPRN 


AB1F 


XGS1 


B6CA 


XPLT 


ACC5 


XIF 


B778 


XPMINU 


AC8D 


XINPUT 


B316 


XPMUL 


AC96 


XINT 


B0E6 


XPNE 


ACBE 


XITBT 


B354 


XPNOT 


ACF9 


XLET 


AAE0 


XPOINT 


BC4D 


XLIST 


B483 


XPOKE 


B24C 


XLOAD 


BAFB 


XPOP 


B841 


XLOAD1 


BB04 


XPOR 


ACEE 


XLOCAT 


BC95 


XPOS 


BA16 


XLPRIN 


B464 


XPPDL 


B022 


XNEW 


A00C 


XPPEEK 


AFE1 


XNEXT 


B6CF 


XPPLUS 


AC84 


XNOTE 


BC36 


XPPOWE 


B165 


XON 


B7ED 


XPPTRI 


B02A 


XOP1 


BBED 


XPRINT 


B3B6 


XOP2 


BBFB 


XPRND 


B08B 


XOPEN 


BBEB 


XPRPRN 


AD7B 


XPAASN 


AD5F 


n XPSEQ 


AC DC 


XPABS 


B0AE 


XPSGE 


ACD5 


XPACOM 


AD79 


XPSGN 


AD19 


XPADR 


B01C 


XPSGT 


ACCC 


XPALPR 


AD86 


XPSIN 


BUB 


XPAND 


ACE3 


XPSLE 


ACB5 


XPASC 


B012 


XPSLPR 


AE26 


XPATN 


B12F 


XPSLT 


ACC5 



XPSNE 


ACBE 


XPSQR 


B157 


XPSTIC 


B026 


XPSTR 


B049 


XPSTRI 


B02E 


XPUMIN 


ACA8 


XPUPLU 


ACB4 


XPUSH 


AD16 


XPUSR 


B0BA 


XPUT 


BC72 


XPVAL 


B000 


XRAD 


B266 


XREAD 


B283 


XREM 


A9E7 


XREST 


B26B 


XRTN 


B719 


XRUN 


B74D 


XSAASN 


AEA3 


XSAVE 


BB5D 


XSAVE1 


BB62 


XSETCO 


B9B7 


XSOUND 


B9DD 


XSTATU 


BC28 


XSTOP 


B793 


XTF 


AD09 


XT I 


AD07 


XTRAP 


B7E1 


XTRUE 


AD05 


XXIO 


BBE5 


ZF1 


DA46 


ZFP 


00D2 


ZFR0 


DA44 


ZICB 


0020 


ZPADEC 


AFBC 


ZPG1 


0080 


ZTEMP1 


00F5 


ZTEMP2 


00C6 


ZTEMP3 


00F9 


ZTEMP4 


00F7 


ZVAR 


B8C0 


ZXLY 


DA48 



283 



Index 



Symbols 



in Operator Name Table 177 

with string literals 130 
(See also XPACOM) 

in Operator Name Table 177 

precedence of 69-70 

with array, in ONT 180 

with PRINT 98 
$ in hexadecimal 115 

in Operator Name Table 177 

in variable names 15, 46 
: (See alphabetic entry for terms 

that begin with ":", like 

:LPRSCAN) 58 

in Operator Name Table 177 

with PRINT 98 
; in Operator Name Table 177 

with PRINT 98 
# in Operator Name Table 178 

with PRINT 98 

< = (See also XPLE, XPSLE) 178-79 

< > (See a/so XPNE, XPSNE) 178-79 

> = (See also XPGE, XPSGE) 178-79 

< (See a/so XPLT, XPSLT) 

in ABML 34-39 

in Operator Name Table 

178-79 
precedence of 56 

> (See also XPGT, XPSGT) 

in ABML 34-39 

in Operator Name Table 
178-79 

precedence of 56 
(See also XPEQ, XPSEQ) 41-42, 

58-64 

in Operator Name Table 
178-79 

precedence of 55-56 
A in Operator Name Table 178 

precedence of 55-56, 58-64 
(See also XPMUL, FMUL, 

FRMUL) 

in Operator Name Table 178 

precedence of 55-56, 58-64 
+ (See also XPPLUS, XPUPLUS, 

FADD, FRADD) 

in Operator Name Table 178 

unary 179, Appendix B 

precedence of 55-56, 58-64 



(See also XPMINUS, XPUMINUS, 
FSUB, FRSUB) 
in Operator Name Table 178 
unary 179, Appendix B 

I (See also XPDIV, FDIV, FRDIV) 

178 

( (See also XPDLPRN, XPALPRN, 

XPSLPRN) 

in variable names 15, 46 
mathematical, in Operator 

Name Table 179 
precedence of 69-70 
string, array, DIM, and func- 
tion, in ONT 179-80 
tokens for 70 

) (Seen/soXPRPRN) 

in Operator Name Table 179 
precedence of 69-70 

: = 34-37 

! 34, 37, 41 

= < 56 

! as EOE operator 34-35, 58-64 

? 95 

Numbers 

6502 microprocessor 1-2, 40 



AADD 202, $AF52 

AADR 66-68 

AAPSTR 191, $AB98 

ABS (See also XPABS) 69, 180, 206 

Absolute Non-Terminal Vector (See 

ANTV) 
ABML (Atari BASIC Meta-Language) 

33-34, 37 
AD Appendix A 
addition (See FADD, FRADD) 
ADR 180 

AMUL202, $AF5D 
AMUL 2 202, $AF46 
AND (See also XPAND) 89, 179 
ANTV (in ABML) 40-42, 44, 162 
APHM 13, 143, $000E 
application high memory 13 
ARGOPS 23, 66, 143, $0080 
ARGP2 192, $AC06 
ARGPOP 192, $ABF2 



285 






Index 



ARGPUSH 65, 191, $ABBA 

ARGSTK 23, 66, 143, $0080 

arguments 56 

Argument Stack 12, 23, 56-67 
entry format 66-68 
example of use 56-64 

arithmetic assignment operator (Sec 
XPAASN) 

arithmetic expressions 12, 55-65 

array variables 15-16, 18, 66-67, 69-70, 
106-7, 127 

Array/String Table (See String/ Array 
Table) 

ARSLVL 66, 144, $00AA 

ARSTKX 144, $00AA 

ASC (See also XPASC) 180, 204 

ASCIN 246, $D800 

ASLA: Appendix A 

assembler 2 

assembly language 2-3 

ATAN[X] 244, $BE77 

Atari BASIC 

as a high-level language 2-5 
location in memory 14 
Meta-Language (ABML) 33 
ROM pointer 143, $A000 

Atari cartridge vectors 272 

ATASCII 9, 47, 88, 90, 116, 135-36 

AT LINE (in error message) 74, 231-32, 
$B9AE 

ATN (See a/so XPATN, ATAN) 180, 207, 
244 

AUXii (i.e., AUX1, AUX2, etc.) 99-100 

B 

BASIC ROM pointer 143, $A000 

binary 115, 119-20 

blanks in program lines 27, 29 

block move routines 20-23 

BNF33 

BREAK 50, 96, 101 

BRKBYT 101, 110, 143, $0011 

buffer (See also INBUFF, OUTBUFF, 

LBUFF) 13, 65, 145 
bugs Preface , 20-21, Appendix B 
BYE (See also XBYE, :SBYE) 105 
BYELOC 143, $E471 
byte 119-20 
BYTE: Appendix A 



CALPRN 70 

carriage return character 177 

cartridge vectors 272 



CDLPRN 70 
CDSLPR 70 
CFLPRN 70 

Change Last Token (in ABML) 41-42 
CHNG (in ABML) 41-42, 45, 162 
CHR$ (See also XPCHR) 180, 205 
CIO 25, 85, 91, 93, 102, 143, SE456 
CIX 26, 29-30, 43, 45, 47 
CLOAD(Seea/soXCLOAD, :SCLOAD) 

84, 237 
CLOG 180 
CLOSE (See k/soXCLOSE, :SCLOSE) 

W0, 146, 239 
CLPRN 70 

CLR (See also XCLR, :SCLR) 83, 103, 224 
CLSALL 242, $BD41 
CLSYS1 99, 241, $BCF1 
CLSYSD 241, $BCF1 
COLDSTART86, 101, 109-UO, 147, 

$A000 
COLOR (See also XCOLOR, :SCOLOR) 
execution 91, 233 
memory location 91-92, 144, 
$00C8 
color registers (See also CREGS) 91-92, 

143 
COMMON (unused command; see 

XCOM, :SCOM) 
compiler 3-4 
constants 33-34, 130 
CONT (See also XCONT, : SCO NT) 

71-72, 225 
:CONT2 183, Appendix B, $A954 
:CONT3 183, Appendix B, $A950 
:CONT4 183, Appendix B, $A95B 
CONTLOW 20-23, 31, 77, 182, $A8FB 
CONTRACT 20-22, 28, 182-83, $A8FD, 

Appendix B 
conversion 

ASCII to floating point 145, 

$00ED-$00F1 
decimal to hexadecimal 116-17 
floating point to ASCII (See also 

CVFASC) 250-52 
floating point to integer (See also 
CVFPI, FPI) 197, 253-55 
hexadecimal to decimal 116 
integer to floating point (See also 
CVIFP) 252-53 
COPEN 237, $BBB6 
COS (See also XPCOS, COS[X]) 105, 180, 

207, 243 
COS[X] 243, SBDB1 
COX 26, 27-30, 43, 45, 48, 97-98, 144, 

$0094 
CPC 43-44, 144, 153, $009D 



286 



Index 



CPU stack 43, 51, 74-75, 109-110 
CREGS 143, S02C4 
CRTGI 143, $BFF9 
CSAVE(Seert/soXCSAVE, :SCSAVE) 

84, 237 
CSLPRN 70 

Current Program Counter (See CPC) 
CVAFP 96, 246, $D800 
CVFASC 98, 250, $$D8E6 
CVFPI (See also FPI) 197, $AD56 
CVIFP 252, $D9AA 
:CVFR0 263, $DC70 

D 

Dl 169, $A705 

DATA (See also XDATA, :SDATA) 

103-104, 110,131,140 
DATAD 103-4, 110, 144, $00B6 
DATALN 103-4, 110, 144, $00B7 
DCBORG 143, $0300 
debugger 2 
decimal 115-17 
:DECINB 265, $DCC1 
definition 

in language creation 33-34 
DEG (See also XDEG, :SDEG) 105, 145, 

211 
DEGFLG 145, $00FB 
deleting lines 28 
DEND 81-82 
DIM (See also XDIM, SUM) 16-17, 66, 

127 

and "(" operator 70, 197 
effects on tables 16-17 
execution 106-7, 210 
DIMENSION TOO SMALL error (See 

also ERRDIM) 96 
direct statement 32, 49, 51-52, 74 
DIRFLG 26, 30-32, 144, $00A6 
Disk Device Dependent Note 

Command 100 
division (SeeFDIV, FRDIV, '/') 
DOS (See also XDOS, :SDOS) 105, 109 
DOSLOC 143, $000A 
DPEEK 122 
DPOKE 122 
DRAWTO (See also XDRAWTO, 

:SDRAWTO) 92-93, 146, 233 
deus ex machina 40-41, 46 
DSPFLG 143, $02FE 
DST 81-82 
DWT 81-82 



ECHNG 45, 154, $A2BA 
Editor (See Program Editor) 
:EGTOKEN (See GETTOK) 
ELADVC 83, 235, $BADD 
END (Secn/soXEND, :SEND) 72-72, 225 
End Of Expression (See EOE operator) 
end-of-statement token (See also EOS) 76 
ENDSTAR 139, 143, $008E 
ENDWT 143, $0088 
English 37 

ENTDTD 85-86, 110, $00B4 
ENTER (See also XEbiTER, :SENTER) 23, 
25, 123, 128, 140 

device 71, 85-86 

execution 85-86, 235 
EOE operator 57-66 
EOL character 58, 95-96, 98, 99-100, 143, 

177 
EOPUSH 65, 189, $AB15 
EOS 169, $A6F8 
EOS2 173, $A773 
EPCHAR 143 
equates 

ICCOM value 146 

ICSTA value 146 

miscellaneous 143 

Run Stack 147 

variables 147 
ERBRTN 230, $B920 
ERGFDE 230, $B922 
ERGFDEL 77, 79, 224, $B74A 
ERLTL 230, $B924 
ERNOFOR 78, 230, $B926 
ERNOLN 75, 230, $B928 
ERNTV 44, 152, $A201 
ERON 230, $B93E 
EROVFL 230, $B92A 
ERRAOS 230, $B92C 
ERRDIM 106, 230, $B92E 
ERRDNO 230, $B918 
ERRINP 96, 230, $B930 
ERRLN 230, $B932 
:ERRM1 231, $B961 
:ERRM2 71, 231, $B974 
ERRNSF 83, 230, $B916 
ERRNUM 72, 101, 110, 144, $00B9 
ERROOD 104, 230, $B934 
ERROR 71, 88, 101, 106, 231, $B940 
error handling 73-74 

and DATA-READ 104 

and DIM 106 

and GOTO 75 

and INPUT 96 

and LOAD 83 



287 



Index 



and SETCOLOR 91 
and SOUND 93 
and TRAP 73, 231 
execution 231 
in I/O 101, 109, 146 
in line processing 25-26, 28 
in LISTing 88 

in statement processing 29-30 
in syntactical analysis 38-39 
messages 230 
missing FOR entry 78 
missing GOSUB entry 79 
missing line number 77 
that stops program 73-74 
ERRPTL 83, 230, $B91A 
ERRSAV 144, $00C3 
ERSVAL 230, SB91C 
ERVAL 91, 93, 230, $B93A 
ESRT (in ABML) 40-41, 44, 47, 162 
:EVEN 249, $D8CE 
EXECNL 32, 49, 75, 183, SA95F 
EXECNS 183, $A962 
Execute Expression (See also EXEXPR) 

12, 55-70, 105, 189-90 
Execution Control 49-54, 75, 77, 83, 

183-85 
EXECUTION OF GARBAGE error (See 

also XERR) 106 
executor (See Program Executor) 
EXEOL 184, $A989 
EXEXPR 64-65, 189, $AAE0 
EXNXT 65, 189, $AAE3 
EXOP 65, 69, 190, $AB20 
EXOPOP 65, 189, $AB0B 
EXOT 65, 189, $AAEE 
EXP (See also XPEXP) 180, 208 
:EXP 162, $A60D 
EXP[X] 268, $DDC0 
EXP10[X] 268, $DDCC 
EXPAND 20-23, 106-7, 144, 181, SA881, 

Appendix B 
EXPINT 65, 190, $AB2E 
EXPL 173, $A76C 
EXPL1 173, $A76F 

EXPLOW 20-22, 31, 77-78, 181, SA875 
exponential operator (i.e., A**B; see 

XPPOWER) 
expressions (See also Execute 
Expression) 
in ABML 34 
rearrangement of 55-65 
Expression Non-Terminal Vector (See 

VEXP) 
Expression Rearrangement Procedure 
(See also expressions, rearrangement 
of) 57 



EXPTST 65, 189, $AAFA 
EXSVOP65, 144, $00AB 
EXSVPR 144, $00AC 
External Subroutine Call (See ESRT) 



FADD 255, $DA66 
FAIL 44-45, 153, $A26C 
false (See XFALSE, :FALSE) 
: FALSE 224, $B788 
FDB: Appendix A 
FDIV 259, $DB28 
files 

LIST-ENTER format (See FLIST) 

SAVE-LOAD format 81-82 
FIXRSTK 226-27, $B825 
FLIST 235, $BAD5 
floating point 126-27 

add (See FADD, FRADD) 

ASCII to fp conversion 145, 

$00ED-$00F1 

fp to ASCII conversion 250-52, 

$D8E6-$D9A9 

fp to integer conversion 253-55, 

$D9D2-$DA5F 

comparisons 196-97 

divide (See FDIV, FRDIV) 

in ROM 14, 143, 246-72, 

$D800-$DFF6 

integer to fp conversion 252-53, 

$D9AA-$D9CF 

load/store 267 

multiply (See FMUL, FRMUL) 

routines 255-67 

subtract (See FSUB, FRSUB) 

zero page work area 143, 145, 

$00D2-$00EC 
FLOG10 270, SDF01 
FMOVER 183, Appendix B, $A947 
FMUL 257 SDADB 
:FNZER0 264, $DCA4 
FOR(Seefl/soXFOR, :SFOR) 12 

entry on Runtime Stack 18-19, 

76-77, 133-34 

execution 77-78, 220-21 

tricks with 131 
FPI 253, $D9D2 
FPORG 143, 246, $D800 
FRO 145, $00D4 
FROM 145, $00D5 
FR1 145, $0OEO 
FR1M 145, $00E1 
FR2 145, $0OE6 

FRAim (i.e., FRA10, FRA20) 266, $DD01 
FRADD 196, $AD3B 



288 



Index 



FRCMP 196, $AD35 
FRDIV 196, $AD4D 
FRE 

floating point memory location 

145, $00DA 

function (See also XPFRE) 180, 204 
FRMUL 196, $AD47 
FRSUB 196, $AD41 
FRUN 236, $BAF7 
FS 172, $A751 
FSTEP 168, $A6DE 
FSUB 255, $DA60 
Function Name Table 180 
functions (See entry under individual 
function name) 



G 



GDI01 101, 239, $BC22 
GDVCIO 100-101, 239, $BC1D 
GET (See also XGET, :SGET) 97, 146, 

239, Appendix B 
GET1 239, Appendix B, $BC82 
GET1INT 192, $ABE9 
GETADR 44, 152, $A215 
:GETCHAR260, $DB94 
:GETDIG 265, $DCB9 
GETINT 99, 192, $ABE0 
GETLL 31, 53, 185, $A9DD 
GETLNUM 151, $A19F 
GETPINT 192, $ABD5 
GETSTMT 31, 52-53, 54, 75, 87, 103-4, 

184, $A9A2 
GETTOK 128, 190, $AB3E 
:GETTOK 77, 79, 223, SB737 
GETVAR 191, $AB89 
GIOCMD 99, 241, $BD04 
GIODVC 99, 240, $BC9F 
GIOPRM 241, $BD02 
GLINE 234, $BA89 
GNLINE 234, $BA80 
GNXTL 31, 51, 53, 185, $A9D0 
GOSUB (See also XGOSUB, :SGOSUB) 
12, 43, 79-80, 103, 127 

entry on Runtime Stack 18-19, 

133-34 

execution 79, 221-22 

in ABML 40, 42 

in Operator Name Table 178 
GOTO (See also XGOTO, :SGOTO) 75, 

123, 128, 177, 221-22 
GRAPHICS (See also XGR, :SGR) 86, 91, 

234 
grammar 33-35, 37 
:GRF 205, $B030 
GRFBAS 143, $0270 



GSTRAD 191, $AB9B 
GWTADR 193, $AC28 

H 

hexadecimal 2, 115-17 
high level languages 3 
high memory address 13 
HIMEM 143, $02E5 
HMADR 13, 143, $02E5 

I 

ICCOM 146, $0342 

ICSTA 146, $0343 

IF (See also XIF, :SIF) 76, 154, 224 

IFA 174, $A799 

INBUFF 23, 25, 47, 88, 91, 98 

INPUT (See h/soXINPUT, :SINPUT) 
95-96, 143, 145, 213-14, Appendix B 

INT (See also XPINT) 180, 206 

interpreter 1, 3-5 

INVAR 46 

I/O 91-93, 95-102, 109, 234-43 

I/O Call Routine 101-2, 241, $BD0A 

IOCB n (i.e., IOCB 0, IOCB 1, etc.) 
85-87, 91-92, 95, 99-101, 105, 110 
close all (See CLSALL) 
control block 146, $0340-$0350 
ICCOM value equates 146 
ICSTA value equates 146 

IOCBORG 143, $0340 

IOCMD 99, 102, 144, $00C0 

IODVC 144, $00C1 

\On (i.e., IOl, 102, etc.) 83, 100, 202-2 

IOTEST86, 91, 93, 100, 202, 240, $BCB3 

ISVAR 46, 241, $BD2F 

ISVAR1 100, 241, $BD2D 



joysticks (See STICK, :STRIG) 
JS Appendix A 



labels 34 

language 

creation of 33-39 
problems with 1-2 
high level 3 

LBUFF 23, 25, 30, 145, $0580 

LDDVX 240, $BCA6 

LDIOSTA 241, $BCFB 

LELNUM 87, 144, $00AD 

LEN (See also XPLEN) 180, 203 



289 



Index 



LET (See also Execute Expression, XLET, 

:SLET)8, 11,29,42, 105 
LIFO (last-in, first-out) stack 12, 43, 133 
Line Buffer 23, 25-26 
line number 27-28, 49-50, 52 
line processing 25-28, 31-32, 95-96 
LINE TOO LONG error (See also ERLTL) 

25-26, 43, 48 
LIST (See also XLIST, :SLIST) 15, 25, 
123, 1 28, 129, 139-40 

device 71, 242 

entry in Runtime Stack 19 

execution 86-87, 216-17, 222 

subroutines 88-90 
LISTDTD 86-87, 110, 144, $00B5 
:LLINE 87, 88, 218-19, $B55C 
LLNGTH 50, 54, 72, 144, $009F 
LMADR 13, 143, $02E7 
LOAD (See also XLO AD, :SLOAD) 
81-86, 109, 123, 139-40 

as block (See LSBLK) 

execution 83-84, 236 

file format 81-82 
LOADFLG 109-110, 144, S00CA 
LOCAL: Appendix A 
LOCATE (See also XLOCATE, 

:SLOCATE) 92, 240, Appendix B 
LOG (See also XPLOG) 180, 208, 270, 

$DECD 
LOG10 (See also XPL10) 208 
LOG10[X] 270, $DED1 
LOMEM 23, 115 
LI 176, $A7C0 
low memory address 13 
LPRINT (See a/so XLPR1NT, :SLPRINT) 

98-99, 216 
:LPRTOKEN 71, 88-89, 90, 218, $B535 
:LPTWB218, $B54F 
LSBLK 237, SBB88 
:LSCAN 89-90, 217-18, SB50C 
LSRA: Appendix A 
:LSTMT 88-89, 219-20, $B590 
L2 176, $A7C4 

M 

machine language 1-2 

macros Appendix A 

mantissa 127 

MAXCIX 26, 29, 144, $009F 

MDESUP 265, $DCE0 

MEMFULL 230, $B93C 

memo pad 105 

memory 

management routines 20-23 
organization 13-14 
pointer addresses 13, 83 



MEMTOP 20-21, 143, $0090 

MEOLFLG 143, $0092 

meta-language 33 

MOD (See modulo) 

modulo 120-22 

multiplication (SeeFMUL, FRMUL, '*') 

multipurpose buffer 13, 65, 82, 110 

:MV6RS228, $B88F 

MVFR0E 267, $DD34 

MVFR12 266, $DD28 

MVLNG 183, Appendix B 

N 

NEXT (See also SNEXT) 18, 131 
execution 78-79, 222-23 
in Pre-compiler 43-45, 151, $A1E2 
NEW (See a/so XNEW, :SNEW) 109-110, 

123, 128 
NFP 164, $A672 
NFSP 176, $A7CE 
NFUN 164, A65F 
NFUSR 164, $A669 
NIBSH0 261, $DBEB 
NMAT 164, $A651 
NMAT2 164, $A659 
non-terminal 35, 40 
NOP 163, $A62E 
NORM 262, $DC00 

NOT (See also XPNOT) 178, Appendix B 
NOTE (See also XNOTE, :SNOTE) 100, 

239 
NSMAT 173, $A777 
NSML 174, $A78C 
NSML2 174, $A790 
NSVAR 169, $A708 
NSVRL 169, $A710 
NSV2 170, $A714 
NULL (in ABML) 162 
numeric constants 89, 131 
numeric variable 7-8, 95 
NV 162, $A622 
NVAR 163, $A64C 
NXSC 44, 153, $A2A1 
NXTSTD 50, 54, 72, 144, $00A7 

o 

ON (See also XON, :SON, ONI) 80, 226 

ONI 173, SA768 

OPD 171, $A72C 

OPEN (See also XOPEN, :SOPEN, 

COPEN, SOPEN) 99-100, 123, 146, 

238 
Operating System (OS) 13-14, 92-93, 

105, 109 



~ 



290 



Index 



Operator Execution Table (See also 

OPETAB) 9, 187-89 
Operator Name Table (See also 

OPNTAB) 9, 46, 89, 135-36, 177-80 
Operator Precedence Table (See also 
OPRTAB) 9-10, 56, 137-38, 193-94, 
Appendix B 
Operator Stack 12, 23, 56-67 
entry format 66 
example of use 56-64 
Operator Token (in ABML) 42, 131 
operators 33-34 
array 69 
EOE 57-66 

BASIC functions as 69 
execution of 69-70 
precedence of 56-64, 69 
SOE 57-66 
token 89 
OPETAB (See also Operator Execution 

Table) 187, $AA70 
OPNTAB (See also Operator Name 

Table) 135-36, 177, $A7E3 
OPRTAB (See also Operator Precedence 

Table) 137-38, 193, $AC3F 
OPSTKX 66, 144, $00A9 
OR (See also XPOR) 

in ABML 41, 44-45, 162 
in Operator Name Table 179 
OUTBUFF 23, 26-28, 30-31, 45, 143, 
$0080 



PADDLE (See also XPPDL) 180, 204 
Pascal 3 
pass/fail 37-40 
PEEK(Seea/soXPPEEK)69, 115, 219-22, 

137-38, 180, 203 
PEL 175, $A7A9 
PELA 175, $A7B2 
PES 175, $A7AC 
PILOT 3 

PL6RS 229, $B89E 

PLOT (See also XPLOT, :SPLOT) 92, 234 
PLYEVL 267, $DD40 
POINT (See also XPOINT, :SPOINT) 

100-101, 239 
pointers 

line processing 25-27 

memory 13 

multipurpose buffer 65 

tables 20, 83, 110, 143 
POKADR 144, $0095 
POKE (See also XPOKE, : SPOKE) 105 

execution 105, 211 

how to use 119-22 



polynomial evaluation (See also 

PLYEVL) 267 
POP (See a/so XPOP, :SPOP) 18, 227 
BASIC command 80 
in Pre-compiler 44, 152, $A252 
POP1 192, $AC0F 
POPRSTK 77, 78-80, 227, $B841 
POSITION (See also XPOS, :SPOS) 92, 

233 
power of (See also XPPOWER) 208-9 
PR1 175, $A7A0 
PR2 175, $A7A6 
PRCHAR 89, 235, $BA9F 
PRCR 242, $BD6E 
PRCX 92, 99, 235, $BAA1 
PREADY 242, $BD57 
precedence (See operators, Operator 

Precedence Table) 
Pre-compiler 10-11, 25-26, 33-48 
pre-compiling interpreter 5 
PRINT (See a/soXPRINT, : SPRINT) 

97-98, 110, 123, 127, 214-16 
Program Editor 11, 25-32, 110, 

Appendix B 
Program Executor 8, 11-12, 32 
PROMPT 144, $00C2 
prompt 95 
PS 176, $A7BC 

PSHRSTK 77, 78-79, 221, $B683 
PSL 175, $A7B6 
PSLA 175, $A7B9 
PSn (i.e., PS1, PS2, etc.) 57, 59-65 
PTABW 97, 144, $O0C9 
PTRIG (See also XPPTRIG) 180, 204 
PUSH 43, 152, $A228 
PUSR 177, $A7DA 
PUSR1 177, $A7DD 
PUT (See also XPUT, :SPUT) 92, 99, 146, 

239 
PUTCHAR 235, $BA9F 



R 



RAD (See also XRAD, :SRAD) 105, 211 
RADFLG 105, 110, 145, $00FB 
RAM tables 10, 81-82 
:RCONT228, $B872 
READ (See a/so XREAD, :SREAD) 95-96 
bugs Appendix B 
entry in Runtime Stack 19 
execution 103-4, 211-13, 222 
READY (See also PREADY) 51-52, 110, 

242 
rearrangement (See expressions, 

rearrangement of) 
Relative Non-Terminal Vectors (in 
ABML) 42 



291 



Index 



REM (See also XREM, :SREM) 106, 131, 

140, 154 
RESTORE {See also XRESTORE, 

:SRESTORE) 103-4, 211 
RETURN (See also XRTN, :SRET) 12, 18, 

79-80, 223-24 
Return (in ABML) 41 
:REXPAN228, $B878 
Richard's Rule Appendix B 
RISASN 96 

RND (See also XPRND) 37, 69, 180, 206 
RNDLOC 143, $D20A 
RNTV 44 

ROLA: Appendix A 
ROM 143, $A000 
ROM tables 9-10, 135-36 
RORA: Appendix A 
RSHF0E 263, $DC62 
RSHFT0 263, $DC3A 
RSHFT1 263, $DC3E 
RSTPTR229, $B8AF 
RSTSEOL 100, 242, $BD99 
RTN (in ABML) 41, 44-45, 162 
RTNVAR 96, 193, $AC16 
RTS 45, 51, 96, 106 
RUN (See also XRUN, :SRUN, 
RUNINIT) 

as direct statement 49, 52 

execution 71-73, 224 

initialization 103, 105 

with implied LOAD (See also 

FRUN) 235 
RUNINIT 230, $B8F8 
RUNSTK 19, 143, $008E 
Runtime Stack 10, 14 

and FOR, NEXT, GOSUB, 

RETURN 76-80 

entry format 18-19 

listing 133-34 

pointer to 19 



SADR 66-68 

SAP (Simple Arithmetic Process) 33-39 
SAVCUR 144, $00BE 
:SAVDEX228, $B88A 
SAVE (See also XSAVE, :SSAVE) 81-83, 
85-86, 139 

as block (See LSBLK) 

execution 82-83, 237 

file format 81-82 
SAVE "C:" 84 
SAVEOP 57, 59-64 
:SAVRTOP228, SB881 
:SBYE167, $A6BE 



scalar 126 

SCANT 89-90, 97-98, 144, $00AF 

SCLOAD 167, $A6BE 

SCLOSE 170, SA721 

SCLR 167, $A6BE 

SCOLOR 167, $A6BD 

SCOM 173, SA760 

SCONT 167, $A6BE 
SCRADR 90 
screen editor 25 
SCRX 92, 143, $0055 
SCRY 92, 143, $0054 
:SCSAVE167, $A6BE 
SCVECT 272, $BFF9 

SDATA 176, $A7CB 

SDEG 167, $A6BE 

SDIM 173, $A760 

SDOS 167, $A6BE 

SDRAWTO 172, $A75D 
SEARCH 29, 47, 135, 158, $A462 

SEND 167, $A6BE 

SENTER 170, $A724 

SETCODE 27-29, 154, $A2C8 

SETCOLOR (See also XSETCOLOR, 

:SSETCOLOR) 91-92, 232 
SETDZ 242, $BD72 
SETLINE 54, 226, $B818 
SETLN1 50, 54, 226, $B81B 
SETSEOL99, 242, $BD79 
SFNP 177, $A7D6 
:SFOR167, $A6D2 
SFP 165, $A678 
SFUN 165, SA68A 
:SGET 168, $A6E8 
SGN (See also XPSGN) 180 

SGOSUB 167, $A6BD 

SGOTO 167, $A6BD 

SGR 167, $A6BD 
SICKIO 101, 240, $BCB9 
:SIF174, $A794 
SIN (See also XPSIN, SIN[X]) 105, 180, 

207, 243 
SIN[X] 243, $BDA7 
:SINPUT 169, Appendix B, $A6F4 
SKBLANK 29, 261, $DBA1 
SKCTL 143, $D20F 
SKPBLANK 260-61, $DBA1 
:SLET167, $A6C0 
SLIS 171, $A73C 

SLIST 171, $A733 

SLOAD 170, $A724 

SLOCATE 168, $A6E2 

SLPRINT 169, $A700 
SMAT 165, $A694 
SMAT2 166, $A69C 
:SNEW167, $A6BE 



292 



Index 



:SNEXT168, $A6EA 
:SNOTE172, $A74A 
SNTAB (See also Statement Name Table) 

115, 135-36, 159, $A4AF 
SNX2 86, 101, 148, $A053 
SOE operator 57-66 
: SON 173, $A763 
SOP 166, $A6A2 
SOPEN 238, $BBD1 
:SOPEN170, $A71A 
SOUND (See a/so XSOUND, :SSOUND) 

93, 232 
sound registers (See also SREGu, 

:SKCTL)93, 143 
:SPLOT172, $A75D 
:SPOINT172, $A74A 
: SPOKE 172, $A75D 
:SPOP167, $A6BE 
:SPOS172, $A75D 
: SPRINT 169, $A6FC 
:SPUT 166, $A6BA 
speed comparisons 3-5 
SQR (See also XPSQR, SQR[X] 180, 208, 

245 
SQR[X] 245, $BEE3 
:SRAD167, $A6BE 
SRCADR 29, 43, 48, 144, $0095 
SRCONT 45-46, 154, $A2E6 
:SREAD 169, Appendix B, $A6F5 
SREGn (i.e., SREG1, SREG2, etc.) 143, 

$D208, SD201-2 
SREM 176, $A7C8 
SREST 168, $A6EF 
SRET 167, $A6BE 
SRUN 170, $A727 
SSAVE 170, $A724 
SSETCOLOR 172, $A75B 
SSOUND 172, $A759 
SSTATUS 171, $A741 
SSTOP 167, $A6BE 
ST (See Statement Table) 
stack (See also Argument Stack, 

Operator Stack, Runtime Stack, 

CPU stack) 2, 12 
STACK OVERFLOW error (See also 

ERRAOS) 66 
STARP 18, 139, 143, $008C 
Start Of Expression (See SOE Operator) 
STAT 171, $A744 
statement 

execution 50-51 
processing 28-31 
Statement Execution Table (See also 

STETAB) 9, 185-87 
Statement Name Table (See also SNTAB) 

9, 40, 135-36, 159-61 



Statement Name Token 8, 12, 106 
Statement Syntax Table 10-11, 33, 40 
Statement Table 10-11, 14, 49-50, 52 

entry format 17, 131 

in LIST 87-88 

in NEW 110 

in SAVE and LOAD 81-82 

listing in token form 129-31 

processing 31 
STATUS (Sees/soXSTATUS, :SSTATUS) 

W0, 146, 239 
:STCHAR264, $DC9F 
STCOMP 165, $A67E 
STENUM 29, 48, 144, $00AF 
STEP 

execution 77-78 

in Operator Name Table 178 

in Runtime Stack 19 
STETAB (See also Statement Execution 

Table) 185, $AA00 
STICK (See also XPSTICK) 180, 204 
STINDEX 65, 87-88, 144, $00A8 
STKLVL 43, 144, $00A9 
STMLBD 29-30, 144, $00A7 
STMTAB 17, 131, 143, $0088 
STMCUR 20, 31-32, 49-54, 64, 72, 88, 

143, $008A 
STMSTRT 30, 144, $00A8 
:STNUM264, $DC9D 
STOP (See also XSTOP, : SSTOP) 50, 

72-72, 124, 225 
STOPLN 71-72, 110, $00BA 
STR (See a/so XPSTR) 

function 205 

routine 165, $A682 
STR$ 180 

: STRAP 167, $A6BD 
STRCMP 202, $AF81 
STRIG (See also XPSTRIG) 180, 204 
String/ Array Table 10, 106-7, 127 

pointers into 15-16, 143 

entry format 18 

SAVEing 139 

use of, in Execute Expression 

66-67 
string 

assign operator 200-202 

bug Appendix B 

comparisons (See STRCMP) 

constants (literals) 89, 131 

variables 15-18, 66-67, 70, 96, 107 
subscripts (See arrays, '(' and ',') 
subtraction (See FSUB, FRSUB, '-') 
SVAR 165, $A68F 
SVCOLOR 92, 143, $02FB 
SVDISP 77, 79, 144, $00B2 



293 



Index 



SWNTP 26, 144, $OOAD 

SVWTE 27, 144, $C0B1 

:SXIO170, $A718 

symbols 1, 4 

in language creation 33-39 

SYN: Appendix A 

SYNENT42, 151, $A1C3 

SYNTAX 74, 148, $A060 

syntax 1, 10-11, 23, 29-30 
analysis of 37-39 
bugs with Appendix B 
creation of 35-39 
instruction codes 40-42 
memory organization 148-53 
tables 40-42, 162-77 

syntaxer (See Pre-compiler) 

Syntax Stack 23, 43 



tables 9-70 

Function Name Table 180 
Operator Execution Table 9, 

187-89 
Operator Name Table 9, 46, 89, 

135-36, 177-80 
Operator Precedence Table 9-10, 

56, 137-38, 193-94, Appendix B 
RAM tables 11, 81-82, 110, 143 
ROM tables 9-10 
Runtime Stack 10, 14, 18-19, 

76-80, 133-34 
Statement Execution Table 9, 

185-87 
Statement Name Table 9, 40, 

135-36, 159-61 
Statement Syntax Table 10-11 
Statement Table 10, 14, 17, 31, 

49-50, 52, 81-82, 110, 129-31 
String/Array Table 10, 13, 18, 

106-7, 127 
syntax tables 40-42, 162-77 
Variable Name Table 10, 13, 15, 

26, 46, 81-82, 110, 123, 135-36 
Variable Value Table 10, 13, 15-16, 

27, 46, 66-67, 78, 81-82, 106-7, 
125-28 

TENDST51, 52, 185, $A9E2 

terminal symbol 34-36 

TERMTST 44-45, 154, $A2A9 

TEXP 172, $A755 

THEN (See also XIF, :SIF) 58, 76, 178 

TNCON 47, 157, $A400 

TNVAR 46, 155, $A32A 

TO 131, 178 

tokens 5-8, 15, 17, 88-89, 135 



TOPRSTK 143, $0090 
transcendental functions 207-9 
translators 1-3 
TRAP (See alsoXTRAP, : STRAP) 73, 76, 

225, 231 
TRAPLN 73, 76, 110, 144, $00BC 
true (See XTRUE) 
TSCON 47, 157-58, $A428 
TSLNUM 27, 52-53, 77, 79, 87, 144, 

$O0AO 
TSTALPH 157, $A3F3 
:TSTCHAR261, $DBBB 
TSTEND 230, $B910 
TSTNUM 261, $DBAF 
TSVAR 155, $A32E 
TVAR 155, $A330 

U 

UNARY 162, $A618 

unary + and - 179, Appendix B 

USR (See also XPUSR) 180, 206 



VAL (See also XPVAL) 180, 204 
Variable Name Table 10, 13, 26, 46 

entry format 15 

in NEW 110 

in SAVE and LOAD 81-82 

listing 123-24, 135-36 
variables (See also numeric v, string 
v, array v) 8, 95 

finding and listing 139-40 

listing 123-28 

tokens 8, 88-89 
Variable Value Table 10, 13, 27, 46, 
66-67, 78, 106-7 

entry format 15-17 

in SAVE and LOAD 81-82 

listing 125-28 
VEXP (in ABML) 41, 44-45, 162 
VNT (See Variable Name Table) 
VNTD 20, 123, 143, $0084 
VNTP 15, 123, 139, 143, $0082 
VNUM 66-68 

VVT (See Variable Value Table) 
VVTP 17, 143, $0086 



w 

WARMFLG 109-110, 143, $0008 
WARMSTART 109-110, 148, $A04D 
WORD 122 
WVVTPT 144, $009D 



294 



index 



XBYE 205, 185, $A9E8 

XCLOAD 237, $BBAC 

XCLOSE 200, 239, $BC1B 

XCLR 72, 224, $B766 

XCMP 196, $AD26 

XCOLOR 92, 233, $BA29 

XCOM 210, $B1D9 

XCONT 72-72, 225, $B7BE 

XCSAVE 237, $BBA4 

XDATA 203, 185, $A9E7 

XDEG 205, 211, $B261 

XDIM 206-7, 210, $B1D9 

XDOS 205, 185, $A9EE 

XDRAWTO 91, 92-93, 233, SBA31 

XEND 52, 72-72, 225, $B78D 

XENTER 85-86, 235, $BACB 

XEOS 167, $A6BD 

XERR 206, 230, $B91E 

XFALSE 195, $AD00 

XFOR 51, 77-78, 220, SB64B 

XFORM 269, $DE95 

XGET 97, 239, $BC7F 

XGOSUB 79, 87, 103, 221, SB6A0 

XGOTO 75, 76, 79-80, 221, $B6A3 

XGR 92, 234, $BA50 

XGS 222, $B6C7 

XIF 76, 224, $B778 

XIN0 96, 213, $B326 

XINA 95-96, 104, 213, $B335 

x index 69-70 

XINPUT 95-96, 104, 213, $B316 

XINT 207, $B0E6 

XINX 96, 214, $B389 

XIO (See also XXIO, :SXIO) 99-100, 238 

XIRTS 96, 214, $B3A1 

XISTR 96, 213, $B35E 

XLET 205, 189, $AAE0 

XLIST 51, 86-87, 216, $B483 

XLOAD 72, 83-84, 236, $BAFB 

XLOCATE 92, 240, $BC95 

XLPRINT 98-99, 216, $B464 

XNEW 109, 220, 147, $A00C 

XNEXT 78-79, 222, $B6CF 

XNOTE 200, 239, SBC36 

XON 80, 226, $B7ED 

XOPEN 99, 238, $BBEB 

XOP1 99, 238, $BBED 

XPAASN 197, $AD5F 

XPABS 206, $B0AE 

XPACOM 197, $AD79 

XPALPRN 198, $AD86 

XPAND 195, $ACE3 

XPASC 204, $B012 

XPATN 207, $B12F 



XPCHR 205, SB067 

XPCOS 207, $B125 

XPDIV 194, $ACA8 

XPDLPRN 197, $AD82 

XPEOL 215, $B446 

XPEOS 98, 215, $B446 

XPEQ 195, $ACDC 

XPEXP 208, $B14D 

XPFRE 204, $AFEB 

XPGE 195, $ACD5 

XPGT 195, $ACCC 

XPINT 206, $B0DD 

XPL10 208, $B143 

XPLE 195, $ACB5 

XPLEN 203, SAFCA 

XPLOG 208, $B139 

XPLOT 92, 234, $BA76 

XPLT 195, $ACC5 

XPMINUS 194, $AC8D 

XPMUL 69, 194, SAC96 

XPNE 195, $ACBE 

XPNOT 195, SACF9 

XPOINT 200, 239, $BC4D 

XPOKE 205, 211, $B24C 

XPOP 80, 227, $B841 

XPOR 195, $ACEE 

XPOS 92, 233, $BA16 

XPPDL (See also :GRF) 204, $B022 

XPPEEK 203, $AFE1 

XPPLUS 194, $AC84 

XPPOWER 208, $B165 

XPPTRIG (See also :GRF) 204, $B02A 

XPR0 98, 214, $B3BE 

XPRINT 86, 97-98, 214, $B3B6 

XPRIOD 98, 215, $B437 

XPRND 206, $B08B 

XPRPRN 197, $AD7B 

XPRTN 98, 215, $B458 

XPSEQ 195, $ACDC 

XPSGE 195, $ACD5 

XPSGN 196, $AD19 

XPSGT 195, $ACCC 

XPSIN 207, $B11B 

XPSLE 195, $ACB5 

XPSLPRN 199, $AE26 

XPSLT 195, $ACC5 

XPSNE 195, $ACBE 

XPSQR 208, $B157 

XPSTICK (See also :GRF) 204, $B026 

XPSTR 205, $B049 

:XPSTR98, 215, $B3F8 

XPSTRIG (See also :GRF) 204, $B02E 

XPSxxxx (i.e., string operator execution 

routines) 195 
XPTAB 98 
XPUMINUS 194, Appendix B, $ACA8 



295 



Index 



XPUPLUS 194, $ACB4 

XPUSR 206, $B0BA 

XPUT 99, 239, $BC72 

XPVAL 204, $B000 

XPxxxx (i.e., operator and function 

execution routines) 69, 194-97, 

203-9 
XRAD 105, 211, $B266 
XRD3 96, 212, $B2D0 
XREAD 103-4, 211, $B283 
XREM 206, 185, $A9E7 
XREST 104, 211, $B26B 
XRTN 79, 87, 104, 223, $B719 
XRUN 51, 71-73, 224, $B74D 
XSAASN 200, $AEA3 
XSAVE 82-83, 237, $BB5D 
XSETCOLOR 91-92, 232, $B9B7 
XSOUND 93, 232, $B9DD 
XSPV 200, $AE96 
XSTATUS 100, 239, $BC28 
XSTOP50, 72-72, 96, 225, $B793 
XTRAP 76, 225, $B7E1 
XTRUE 195, $AD05 
XXIO 99, 238, $BBE5 



i/ index 69-70 ^ 

z 

Z = [X-C]/[X + C] (See also XFORM) 

269-70 
zero default with DIM 127 
zero page 

floating point work area 143 

pointers 20, 110, 143-44 

RAM locations 144 dm k 

ZFP 143, $00D2 
ZICB 143, $0020 

ZPADEC 203, $AFBC •* 

ZPG1 143, $0080 
ZVAR229 / $B8C0 _ 



296 



If you've enjoyed the articles in this book, you'll find the 
same style and quality in every monthly issue of COMPUTE! 
Magazine. Use this form to order your subscription to 
COMPUTE! 



For Fastest Service, 
Call Our Toll-Free US Order Line 

800-334-0868 

In NC call 919-275-9809 



COMPUTE! 

P.O. Box 5406 
Greensboro, NC 27403 



My Computer Is: 

□ PET [J Apple □ Atari □VIC □Other. 



. □ Don't yet have one.. 



□ $20.00 One Year US Subscription 

□ $36.00 Two Year US Subscription 

□ $54.00 Three Year US Subscription 

Subscription rates outside the US: 

□ $25.00 Canada 

Jt $38.00 Europe, Australia, New Zealand/Air Delivery 

□ $48.00 Middle East, North Africa, Central America/Air Mail 

□ $68.00 Elsewhere/Air Mail 

Z\ $25.00 International Surface Mail (lengthy, unreliable delivery) 



Name 






Address 


City 


State 


Zip 


Country 



Payment must be in US Funds drawn on a US Bank; International Money 
Order, or charge card. 

□ Payment Enclosed □ VISA 

□ MasterCard □ American Express 

Ace t. No. Expires / 



297 



COMPUTE! Books 

P.O. Box 5406 Greensboro, NC 27403 

Ask your retailer for these COMPUTE! Books. If he or she 
has sold out, order directly from COMPUTE! 

For Fastest Service 
Call Our TOLL FREE US Order Line 

800-334-0868 

In NC call 919-275-9809 



Quantity Title 

The Beginner's Guide to Buying A Personal 

Computer 

COMPUTED First Book of Atari 

Inside Atari DOS 

COMPUTEI's First Book ot PET/CBM 

Programming the PET/CBM 

Every Kid's First Book of Robots and 

Computers 

COMPUTEI's Second Book of Atari 

COMPUTEI's First Book of VIC 

COMPUTEI's First Book of Atari Graphics 

Mapping the Atari 

HomeEnergyApplicationsOnYour 

Personal Computer 

Machine Language for Beginners 



Price 

$ 3.95" 

$12.95* 

$19.95* 

$12.95* 

$24.95*** 

$ 4.95** 

$12.95* 

$12.95* 

$12.95* 

$14.95" 

$14.95* 

$12.95* 

' Add $2 shipping and handling. Outside US add $5 air mail; $2 
surfacemail. 
' ' Add $1 shipping and handling. Outside US add $5 air mail; $2 

surfacemail. 
"' Add $3 shipping and handling. Outside US add $10 air mail; $3 
surfacemail. 

Please add shipping and handling for each book 
ordered. 

Total enclosed or to be charged. 



Total 



All orders must be prepaid (money order, check, or charge). All 
payments must be in US funds. NC residents add 4% sales tax. 

□ Payment enclosed Please charge my: □ VISA □ MasterCard 

□ American Express Acc't. No. Expires / 

Name 

Address 



Ci1y_ 



State 



^p_ 



Country 



Allow 4-5 weeks for delivery. 



299 






7 






m 

m 

m 
m 

• 

• 
• 



• 



The Atari BASIC Sourcebook 

Everything You Always Wanted to Know 
about the Making of a Computer Language 



• When you type in BASIC programs and run them, what is 
really going on inside the computer? 

• How does the computer know how to handle a FOR-NEXT 
loop and where it should go when it meets a RETURN? 

• Where do ERROR messages come from? 

• How does the computer decide which mathematical opera- 
tion to perform first? 

• Why do some processes take so long, when others are almost 
instantaneous? 

• What sometimes causes the computer to lock up when you 
delete lines from your program? 

• How does the computer know what to do when it sees words 
and symbols like GOTO, INT, CHR$, *, + , and > ? 

• How can your machine language programs take advantage 
of some of the sophisticated routines in Atari BASIC? 

The creators of Atari BASIC have now revealed their own 
work. Even if you aren't a machine language programmer, 
you'll find this book a fascinating exploration of a computer 
language. Now you can understand exactly why your pro- 
grams work as they do. And if you are a machine language 
user, the source listing will let you see exactly where to enter 
Atari BASIC to use the powerful routines built into the 
language. 



ISBN 0-942386-15-9 



$12.95